meerschaum 3.0.0rc4__py3-none-any.whl → 3.0.0rc8__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 +435 -0
- meerschaum/_internal/docs/index.py +1 -2
- meerschaum/_internal/entry.py +44 -8
- meerschaum/_internal/shell/Shell.py +115 -24
- meerschaum/_internal/shell/__init__.py +4 -1
- meerschaum/_internal/static.py +4 -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 +2 -2
- meerschaum/api/_oauth2.py +47 -4
- meerschaum/api/dash/callbacks/dashboard.py +29 -0
- meerschaum/api/dash/callbacks/jobs.py +3 -2
- meerschaum/api/dash/callbacks/login.py +10 -1
- meerschaum/api/dash/callbacks/register.py +9 -2
- meerschaum/api/dash/pages/login.py +2 -2
- meerschaum/api/dash/pipes.py +72 -36
- 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 +32 -12
- 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 +93 -79
- meerschaum/connectors/sql/_users.py +8 -1
- meerschaum/connectors/valkey/_ValkeyConnector.py +3 -3
- meerschaum/connectors/valkey/_pipes.py +7 -5
- meerschaum/core/Pipe/__init__.py +45 -71
- 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 +146 -36
- meerschaum/jobs/systemd.py +7 -2
- meerschaum/plugins/__init__.py +277 -81
- meerschaum/utils/daemon/Daemon.py +197 -42
- 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/_shell.py +33 -9
- meerschaum/utils/misc.py +22 -38
- meerschaum/utils/packages/__init__.py +15 -13
- meerschaum/utils/packages/_packages.py +1 -0
- meerschaum/utils/pipes.py +33 -5
- meerschaum/utils/process.py +1 -1
- meerschaum/utils/prompt.py +172 -143
- 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.0rc4.dist-info → meerschaum-3.0.0rc8.dist-info}/METADATA +3 -1
- {meerschaum-3.0.0rc4.dist-info → meerschaum-3.0.0rc8.dist-info}/RECORD +116 -110
- meerschaum/config/_environment.py +0 -145
- {meerschaum-3.0.0rc4.dist-info → meerschaum-3.0.0rc8.dist-info}/WHEEL +0 -0
- {meerschaum-3.0.0rc4.dist-info → meerschaum-3.0.0rc8.dist-info}/entry_points.txt +0 -0
- {meerschaum-3.0.0rc4.dist-info → meerschaum-3.0.0rc8.dist-info}/licenses/LICENSE +0 -0
- {meerschaum-3.0.0rc4.dist-info → meerschaum-3.0.0rc8.dist-info}/licenses/NOTICE +0 -0
- {meerschaum-3.0.0rc4.dist-info → meerschaum-3.0.0rc8.dist-info}/top_level.txt +0 -0
- {meerschaum-3.0.0rc4.dist-info → meerschaum-3.0.0rc8.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, flush_stdout
|
28
29
|
|
29
30
|
if TYPE_CHECKING:
|
30
31
|
from meerschaum.jobs._Executor import Executor
|
@@ -39,6 +40,10 @@ 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']
|
45
|
+
FLUSH_TOKEN: str = STATIC_CONFIG['jobs']['flush_token']
|
46
|
+
|
42
47
|
|
43
48
|
class StopMonitoringLogs(Exception):
|
44
49
|
"""
|
@@ -46,6 +51,21 @@ class StopMonitoringLogs(Exception):
|
|
46
51
|
"""
|
47
52
|
|
48
53
|
|
54
|
+
def _default_stdout_callback(line: str):
|
55
|
+
if line == '\n' or line.startswith(FLUSH_TOKEN):
|
56
|
+
flush_stdout()
|
57
|
+
return
|
58
|
+
|
59
|
+
if CLEAR_TOKEN in line:
|
60
|
+
clear_screen()
|
61
|
+
return
|
62
|
+
|
63
|
+
if STOP_TOKEN in line:
|
64
|
+
return
|
65
|
+
|
66
|
+
print(line, end='', flush=True)
|
67
|
+
|
68
|
+
|
49
69
|
class Job:
|
50
70
|
"""
|
51
71
|
Manage a `meerschaum.utils.daemon.Daemon`, locally or remotely via the API.
|
@@ -58,6 +78,7 @@ class Job:
|
|
58
78
|
env: Optional[Dict[str, str]] = None,
|
59
79
|
executor_keys: Optional[str] = None,
|
60
80
|
delete_after_completion: bool = False,
|
81
|
+
refresh_seconds: Union[int, float, None] = None,
|
61
82
|
_properties: Optional[Dict[str, Any]] = None,
|
62
83
|
_rotating_log=None,
|
63
84
|
_stdin_file=None,
|
@@ -86,6 +107,10 @@ class Job:
|
|
86
107
|
delete_after_completion: bool, default False
|
87
108
|
If `True`, delete this job when it has finished executing.
|
88
109
|
|
110
|
+
refresh_seconds: Union[int, float, None], default None
|
111
|
+
The number of seconds to sleep between refreshes.
|
112
|
+
Defaults to the configured value `system.cli.refresh_seconds`.
|
113
|
+
|
89
114
|
_properties: Optional[Dict[str, Any]], default None
|
90
115
|
If provided, use this to patch the daemon's properties.
|
91
116
|
"""
|
@@ -112,6 +137,11 @@ class Job:
|
|
112
137
|
|
113
138
|
self.executor_keys = executor_keys
|
114
139
|
self.name = name
|
140
|
+
self.refresh_seconds = (
|
141
|
+
refresh_seconds
|
142
|
+
if refresh_seconds is not None
|
143
|
+
else mrsm.get_config('system', 'cli', 'refresh_seconds')
|
144
|
+
)
|
115
145
|
try:
|
116
146
|
self._daemon = (
|
117
147
|
Daemon(daemon_id=name)
|
@@ -257,7 +287,11 @@ class Job:
|
|
257
287
|
|
258
288
|
return success, f"Started {self}."
|
259
289
|
|
260
|
-
def stop(
|
290
|
+
def stop(
|
291
|
+
self,
|
292
|
+
timeout_seconds: Union[int, float, None] = None,
|
293
|
+
debug: bool = False,
|
294
|
+
) -> SuccessTuple:
|
261
295
|
"""
|
262
296
|
Stop the job's daemon.
|
263
297
|
"""
|
@@ -284,7 +318,11 @@ class Job:
|
|
284
318
|
|
285
319
|
return kill_success, f"Killed {self}."
|
286
320
|
|
287
|
-
def pause(
|
321
|
+
def pause(
|
322
|
+
self,
|
323
|
+
timeout_seconds: Union[int, float, None] = None,
|
324
|
+
debug: bool = False,
|
325
|
+
) -> SuccessTuple:
|
288
326
|
"""
|
289
327
|
Pause the job's daemon.
|
290
328
|
"""
|
@@ -342,7 +380,7 @@ class Job:
|
|
342
380
|
|
343
381
|
def monitor_logs(
|
344
382
|
self,
|
345
|
-
callback_function: Callable[[str], None] =
|
383
|
+
callback_function: Callable[[str], None] = _default_stdout_callback,
|
346
384
|
input_callback_function: Optional[Callable[[], str]] = None,
|
347
385
|
stop_callback_function: Optional[Callable[[SuccessTuple], None]] = None,
|
348
386
|
stop_event: Optional[asyncio.Event] = None,
|
@@ -350,6 +388,10 @@ class Job:
|
|
350
388
|
strip_timestamps: bool = False,
|
351
389
|
accept_input: bool = True,
|
352
390
|
debug: bool = False,
|
391
|
+
_logs_path: Optional[pathlib.Path] = None,
|
392
|
+
_log=None,
|
393
|
+
_stdin_file=None,
|
394
|
+
_wait_if_stopped: bool = True,
|
353
395
|
):
|
354
396
|
"""
|
355
397
|
Monitor the job's log files and execute a callback on new lines.
|
@@ -382,12 +424,6 @@ class Job:
|
|
382
424
|
accept_input: bool, default True
|
383
425
|
If `True`, accept input when the daemon blocks on stdin.
|
384
426
|
"""
|
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
427
|
if self.executor is not None:
|
392
428
|
self.executor.monitor_logs(
|
393
429
|
self.name,
|
@@ -409,29 +445,35 @@ class Job:
|
|
409
445
|
stop_on_exit=stop_on_exit,
|
410
446
|
strip_timestamps=strip_timestamps,
|
411
447
|
accept_input=accept_input,
|
448
|
+
debug=debug,
|
449
|
+
_logs_path=_logs_path,
|
450
|
+
_log=_log,
|
451
|
+
_stdin_file=_stdin_file,
|
452
|
+
_wait_if_stopped=_wait_if_stopped,
|
412
453
|
)
|
413
454
|
return asyncio.run(monitor_logs_coroutine)
|
414
455
|
|
415
456
|
async def monitor_logs_async(
|
416
457
|
self,
|
417
|
-
callback_function: Callable[[str], None] =
|
458
|
+
callback_function: Callable[[str], None] = _default_stdout_callback,
|
418
459
|
input_callback_function: Optional[Callable[[], str]] = None,
|
419
460
|
stop_callback_function: Optional[Callable[[SuccessTuple], None]] = None,
|
420
461
|
stop_event: Optional[asyncio.Event] = None,
|
421
462
|
stop_on_exit: bool = False,
|
422
463
|
strip_timestamps: bool = False,
|
423
464
|
accept_input: bool = True,
|
465
|
+
debug: bool = False,
|
424
466
|
_logs_path: Optional[pathlib.Path] = None,
|
425
467
|
_log=None,
|
426
468
|
_stdin_file=None,
|
427
|
-
|
469
|
+
_wait_if_stopped: bool = True,
|
428
470
|
):
|
429
471
|
"""
|
430
472
|
Monitor the job's log files and await a callback on new lines.
|
431
473
|
|
432
474
|
Parameters
|
433
475
|
----------
|
434
|
-
callback_function: Callable[[str], None], default
|
476
|
+
callback_function: Callable[[str], None], default _default_stdout_callback
|
435
477
|
The callback to execute as new data comes in.
|
436
478
|
Defaults to printing the output directly to `stdout`.
|
437
479
|
|
@@ -457,7 +499,13 @@ class Job:
|
|
457
499
|
accept_input: bool, default True
|
458
500
|
If `True`, accept input when the daemon blocks on stdin.
|
459
501
|
"""
|
502
|
+
from meerschaum.utils.prompt import prompt
|
503
|
+
|
460
504
|
def default_input_callback_function():
|
505
|
+
prompt_kwargs = self.get_prompt_kwargs(debug=debug)
|
506
|
+
if prompt_kwargs:
|
507
|
+
answer = prompt(**prompt_kwargs)
|
508
|
+
return answer + '\n'
|
461
509
|
return sys.stdin.readline()
|
462
510
|
|
463
511
|
if input_callback_function is None:
|
@@ -481,23 +529,26 @@ class Job:
|
|
481
529
|
events = {
|
482
530
|
'user': stop_event,
|
483
531
|
'stopped': asyncio.Event(),
|
532
|
+
'stop_token': asyncio.Event(),
|
533
|
+
'stop_exception': asyncio.Event(),
|
534
|
+
'stopped_timeout': asyncio.Event(),
|
484
535
|
}
|
485
536
|
combined_event = asyncio.Event()
|
486
537
|
emitted_text = False
|
487
538
|
stdin_file = _stdin_file if _stdin_file is not None else self.daemon.stdin_file
|
488
539
|
|
489
540
|
async def check_job_status():
|
490
|
-
|
491
|
-
stopped_event = events.get('stopped', None)
|
492
|
-
if stopped_event is None:
|
541
|
+
if not stop_on_exit:
|
493
542
|
return
|
494
543
|
|
544
|
+
nonlocal emitted_text
|
545
|
+
|
495
546
|
sleep_time = 0.1
|
496
|
-
while sleep_time <
|
547
|
+
while sleep_time < 0.2:
|
497
548
|
if self.status == 'stopped':
|
498
|
-
if not emitted_text:
|
549
|
+
if not emitted_text and _wait_if_stopped:
|
499
550
|
await asyncio.sleep(sleep_time)
|
500
|
-
sleep_time = round(sleep_time * 1.1,
|
551
|
+
sleep_time = round(sleep_time * 1.1, 3)
|
501
552
|
continue
|
502
553
|
|
503
554
|
if stop_callback_function is not None:
|
@@ -517,11 +568,13 @@ class Job:
|
|
517
568
|
break
|
518
569
|
await asyncio.sleep(0.1)
|
519
570
|
|
571
|
+
events['stopped_timeout'].set()
|
572
|
+
|
520
573
|
async def check_blocking_on_input():
|
521
574
|
while True:
|
522
575
|
if not emitted_text or not self.is_blocking_on_stdin():
|
523
576
|
try:
|
524
|
-
await asyncio.sleep(
|
577
|
+
await asyncio.sleep(self.refresh_seconds)
|
525
578
|
except asyncio.exceptions.CancelledError:
|
526
579
|
break
|
527
580
|
continue
|
@@ -536,14 +589,15 @@ class Job:
|
|
536
589
|
if asyncio.iscoroutinefunction(input_callback_function):
|
537
590
|
data = await input_callback_function()
|
538
591
|
else:
|
539
|
-
|
592
|
+
loop = asyncio.get_running_loop()
|
593
|
+
data = await loop.run_in_executor(None, input_callback_function)
|
540
594
|
except KeyboardInterrupt:
|
541
595
|
break
|
542
|
-
if not data.endswith('\n'):
|
543
|
-
data += '\n'
|
596
|
+
# if not data.endswith('\n'):
|
597
|
+
# data += '\n'
|
544
598
|
|
545
599
|
stdin_file.write(data)
|
546
|
-
await asyncio.sleep(
|
600
|
+
await asyncio.sleep(self.refresh_seconds)
|
547
601
|
|
548
602
|
async def combine_events():
|
549
603
|
event_tasks = [
|
@@ -571,17 +625,39 @@ class Job:
|
|
571
625
|
combine_events_task = asyncio.create_task(combine_events())
|
572
626
|
|
573
627
|
log = _log if _log is not None else self.daemon.rotating_log
|
574
|
-
lines_to_show =
|
628
|
+
lines_to_show = (
|
629
|
+
self.daemon.properties.get(
|
630
|
+
'logs', {}
|
631
|
+
).get(
|
632
|
+
'lines_to_show', get_config('jobs', 'logs', 'lines_to_show')
|
633
|
+
)
|
634
|
+
)
|
575
635
|
|
576
636
|
async def emit_latest_lines():
|
577
637
|
nonlocal emitted_text
|
638
|
+
nonlocal stop_event
|
578
639
|
lines = log.readlines()
|
579
640
|
for line in lines[(-1 * lines_to_show):]:
|
580
641
|
if stop_event is not None and stop_event.is_set():
|
581
642
|
return
|
582
643
|
|
644
|
+
line_stripped_extra = strip_timestamp_from_line(line.strip())
|
645
|
+
line_stripped = strip_timestamp_from_line(line)
|
646
|
+
|
647
|
+
if line_stripped_extra == STOP_TOKEN:
|
648
|
+
events['stop_token'].set()
|
649
|
+
return
|
650
|
+
|
651
|
+
if line_stripped_extra == CLEAR_TOKEN:
|
652
|
+
clear_screen(debug=debug)
|
653
|
+
continue
|
654
|
+
|
655
|
+
if line_stripped_extra == FLUSH_TOKEN.strip():
|
656
|
+
line_stripped = ''
|
657
|
+
line = ''
|
658
|
+
|
583
659
|
if strip_timestamps:
|
584
|
-
line =
|
660
|
+
line = line_stripped
|
585
661
|
|
586
662
|
try:
|
587
663
|
if asyncio.iscoroutinefunction(callback_function):
|
@@ -590,6 +666,7 @@ class Job:
|
|
590
666
|
callback_function(line)
|
591
667
|
emitted_text = True
|
592
668
|
except StopMonitoringLogs:
|
669
|
+
events['stop_exception'].set()
|
593
670
|
return
|
594
671
|
except Exception:
|
595
672
|
warn(f"Error in logs callback:\n{traceback.format_exc()}")
|
@@ -608,9 +685,14 @@ class Job:
|
|
608
685
|
except Exception:
|
609
686
|
warn(f"Failed to run async checks:\n{traceback.format_exc()}")
|
610
687
|
|
611
|
-
watchfiles = mrsm.attempt_import('watchfiles')
|
688
|
+
watchfiles = mrsm.attempt_import('watchfiles', lazy=False)
|
689
|
+
dir_path_to_monitor = (
|
690
|
+
_logs_path
|
691
|
+
or (log.file_path.parent if log else None)
|
692
|
+
or LOGS_RESOURCES_PATH
|
693
|
+
)
|
612
694
|
async for changes in watchfiles.awatch(
|
613
|
-
|
695
|
+
dir_path_to_monitor,
|
614
696
|
stop_event=combined_event,
|
615
697
|
):
|
616
698
|
for change in changes:
|
@@ -633,6 +715,27 @@ class Job:
|
|
633
715
|
|
634
716
|
return self.is_running() and self.daemon.blocking_stdin_file_path.exists()
|
635
717
|
|
718
|
+
def get_prompt_kwargs(self, debug: bool = False) -> Dict[str, Any]:
|
719
|
+
"""
|
720
|
+
Return the kwargs to the blocking `prompt()`, if available.
|
721
|
+
"""
|
722
|
+
if self.executor is not None:
|
723
|
+
return self.executor.get_job_prompt_kwargs(self.name, debug=debug)
|
724
|
+
|
725
|
+
if not self.daemon.prompt_kwargs_file_path.exists():
|
726
|
+
return {}
|
727
|
+
|
728
|
+
try:
|
729
|
+
with open(self.daemon.prompt_kwargs_file_path, 'r', encoding='utf-8') as f:
|
730
|
+
prompt_kwargs = json.load(f)
|
731
|
+
|
732
|
+
return prompt_kwargs
|
733
|
+
|
734
|
+
except Exception:
|
735
|
+
import traceback
|
736
|
+
traceback.print_exc()
|
737
|
+
return {}
|
738
|
+
|
636
739
|
def write_stdin(self, data):
|
637
740
|
"""
|
638
741
|
Write to a job's daemon's `stdin`.
|
@@ -724,6 +827,20 @@ class Job:
|
|
724
827
|
self._sysargs = target_args[0] if len(target_args) > 0 else []
|
725
828
|
return self._sysargs
|
726
829
|
|
830
|
+
def get_daemon_properties(self) -> Dict[str, Any]:
|
831
|
+
"""
|
832
|
+
Return the `properties` dictionary for the job's daemon.
|
833
|
+
"""
|
834
|
+
remote_properties = (
|
835
|
+
{}
|
836
|
+
if self.executor is None
|
837
|
+
else self.executor.get_job_properties(self.name)
|
838
|
+
)
|
839
|
+
return {
|
840
|
+
**remote_properties,
|
841
|
+
**self._properties_patch
|
842
|
+
}
|
843
|
+
|
727
844
|
@property
|
728
845
|
def daemon(self) -> 'Daemon':
|
729
846
|
"""
|
@@ -733,20 +850,13 @@ class Job:
|
|
733
850
|
if self._daemon is not None and self.executor is None and self._sysargs:
|
734
851
|
return self._daemon
|
735
852
|
|
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
853
|
self._daemon = Daemon(
|
744
854
|
target=entry,
|
745
855
|
target_args=[self._sysargs],
|
746
856
|
target_kw={},
|
747
857
|
daemon_id=self.name,
|
748
858
|
label=shlex.join(self._sysargs),
|
749
|
-
properties=
|
859
|
+
properties=self.get_daemon_properties(),
|
750
860
|
)
|
751
861
|
if '_rotating_log' in self.__dict__:
|
752
862
|
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.
|