meerschaum 2.3.0rc3__py3-none-any.whl → 2.3.1__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/__init__.py +2 -3
- meerschaum/_internal/arguments/__init__.py +1 -1
- meerschaum/_internal/arguments/_parse_arguments.py +33 -22
- meerschaum/_internal/arguments/_parser.py +4 -7
- meerschaum/_internal/docs/index.py +265 -8
- meerschaum/_internal/entry.py +42 -4
- meerschaum/_internal/shell/Shell.py +84 -72
- meerschaum/actions/__init__.py +21 -11
- meerschaum/actions/show.py +5 -5
- meerschaum/actions/start.py +71 -1
- meerschaum/api/routes/_actions.py +48 -1
- meerschaum/config/_paths.py +1 -0
- meerschaum/config/_version.py +1 -1
- meerschaum/config/static/__init__.py +2 -0
- meerschaum/connectors/__init__.py +1 -2
- meerschaum/connectors/api/APIConnector.py +6 -1
- meerschaum/connectors/api/_actions.py +77 -1
- meerschaum/connectors/api/_pipes.py +85 -84
- meerschaum/jobs/_Job.py +38 -6
- meerschaum/jobs/__init__.py +5 -3
- meerschaum/jobs/{_SystemdExecutor.py → systemd.py} +39 -22
- meerschaum/plugins/_Plugin.py +1 -1
- meerschaum/plugins/__init__.py +2 -1
- meerschaum/utils/daemon/StdinFile.py +1 -0
- meerschaum/utils/daemon/_names.py +14 -12
- {meerschaum-2.3.0rc3.dist-info → meerschaum-2.3.1.dist-info}/METADATA +1 -1
- {meerschaum-2.3.0rc3.dist-info → meerschaum-2.3.1.dist-info}/RECORD +33 -34
- meerschaum/jobs/_LocalExecutor.py +0 -88
- {meerschaum-2.3.0rc3.dist-info → meerschaum-2.3.1.dist-info}/LICENSE +0 -0
- {meerschaum-2.3.0rc3.dist-info → meerschaum-2.3.1.dist-info}/NOTICE +0 -0
- {meerschaum-2.3.0rc3.dist-info → meerschaum-2.3.1.dist-info}/WHEEL +0 -0
- {meerschaum-2.3.0rc3.dist-info → meerschaum-2.3.1.dist-info}/entry_points.txt +0 -0
- {meerschaum-2.3.0rc3.dist-info → meerschaum-2.3.1.dist-info}/top_level.txt +0 -0
- {meerschaum-2.3.0rc3.dist-info → meerschaum-2.3.1.dist-info}/zip-safe +0 -0
@@ -11,14 +11,15 @@ import time
|
|
11
11
|
import json
|
12
12
|
from io import StringIO
|
13
13
|
from datetime import datetime
|
14
|
+
|
14
15
|
import meerschaum as mrsm
|
15
16
|
from meerschaum.utils.debug import dprint
|
16
17
|
from meerschaum.utils.warnings import warn, error
|
17
18
|
from meerschaum.utils.typing import SuccessTuple, Union, Any, Optional, Mapping, List, Dict, Tuple
|
18
19
|
|
19
20
|
def pipe_r_url(
|
20
|
-
|
21
|
-
|
21
|
+
pipe: mrsm.Pipe
|
22
|
+
) -> str:
|
22
23
|
"""Return a relative URL path from a Pipe's keys."""
|
23
24
|
from meerschaum.config.static import STATIC_CONFIG
|
24
25
|
location_key = pipe.location_key
|
@@ -30,10 +31,10 @@ def pipe_r_url(
|
|
30
31
|
)
|
31
32
|
|
32
33
|
def register_pipe(
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
34
|
+
self,
|
35
|
+
pipe: mrsm.Pipe,
|
36
|
+
debug: bool = False
|
37
|
+
) -> SuccessTuple:
|
37
38
|
"""Submit a POST to the API to register a new Pipe object.
|
38
39
|
Returns a tuple of (success_bool, response_dict).
|
39
40
|
"""
|
@@ -59,11 +60,11 @@ def register_pipe(
|
|
59
60
|
|
60
61
|
|
61
62
|
def edit_pipe(
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
63
|
+
self,
|
64
|
+
pipe: mrsm.Pipe,
|
65
|
+
patch: bool = False,
|
66
|
+
debug: bool = False,
|
67
|
+
) -> SuccessTuple:
|
67
68
|
"""Submit a PATCH to the API to edit an existing Pipe object.
|
68
69
|
Returns a tuple of (success_bool, response_dict).
|
69
70
|
"""
|
@@ -89,14 +90,14 @@ def edit_pipe(
|
|
89
90
|
|
90
91
|
|
91
92
|
def fetch_pipes_keys(
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
93
|
+
self,
|
94
|
+
connector_keys: Optional[List[str]] = None,
|
95
|
+
metric_keys: Optional[List[str]] = None,
|
96
|
+
location_keys: Optional[List[str]] = None,
|
97
|
+
tags: Optional[List[str]] = None,
|
98
|
+
params: Optional[Dict[str, Any]] = None,
|
99
|
+
debug: bool = False
|
100
|
+
) -> Union[List[Tuple[str, str, Union[str, None]]]]:
|
100
101
|
"""
|
101
102
|
Fetch registered Pipes' keys from the API.
|
102
103
|
|
@@ -158,13 +159,13 @@ def fetch_pipes_keys(
|
|
158
159
|
|
159
160
|
|
160
161
|
def sync_pipe(
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
162
|
+
self,
|
163
|
+
pipe: mrsm.Pipe,
|
164
|
+
df: Optional[Union['pd.DataFrame', Dict[Any, Any], str]] = None,
|
165
|
+
chunksize: Optional[int] = -1,
|
166
|
+
debug: bool = False,
|
167
|
+
**kw: Any
|
168
|
+
) -> SuccessTuple:
|
168
169
|
"""Sync a DataFrame into a Pipe."""
|
169
170
|
from decimal import Decimal
|
170
171
|
from meerschaum.utils.debug import dprint
|
@@ -303,10 +304,10 @@ def sync_pipe(
|
|
303
304
|
|
304
305
|
|
305
306
|
def delete_pipe(
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
307
|
+
self,
|
308
|
+
pipe: Optional[meerschaum.Pipe] = None,
|
309
|
+
debug: bool = None,
|
310
|
+
) -> SuccessTuple:
|
310
311
|
"""Delete a Pipe and drop its table."""
|
311
312
|
if pipe is None:
|
312
313
|
error(f"Pipe cannot be None.")
|
@@ -327,17 +328,17 @@ def delete_pipe(
|
|
327
328
|
|
328
329
|
|
329
330
|
def get_pipe_data(
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
331
|
+
self,
|
332
|
+
pipe: meerschaum.Pipe,
|
333
|
+
select_columns: Optional[List[str]] = None,
|
334
|
+
omit_columns: Optional[List[str]] = None,
|
335
|
+
begin: Union[str, datetime, int, None] = None,
|
336
|
+
end: Union[str, datetime, int, None] = None,
|
337
|
+
params: Optional[Dict[str, Any]] = None,
|
338
|
+
as_chunks: bool = False,
|
339
|
+
debug: bool = False,
|
340
|
+
**kw: Any
|
341
|
+
) -> Union[pandas.DataFrame, None]:
|
341
342
|
"""Fetch data from the API."""
|
342
343
|
r_url = pipe_r_url(pipe)
|
343
344
|
chunks_list = []
|
@@ -389,10 +390,10 @@ def get_pipe_data(
|
|
389
390
|
|
390
391
|
|
391
392
|
def get_pipe_id(
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
393
|
+
self,
|
394
|
+
pipe: meerschuam.Pipe,
|
395
|
+
debug: bool = False,
|
396
|
+
) -> int:
|
396
397
|
"""Get a Pipe's ID from the API."""
|
397
398
|
from meerschaum.utils.misc import is_int
|
398
399
|
r_url = pipe_r_url(pipe)
|
@@ -411,10 +412,10 @@ def get_pipe_id(
|
|
411
412
|
|
412
413
|
|
413
414
|
def get_pipe_attributes(
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
415
|
+
self,
|
416
|
+
pipe: meerschaum.Pipe,
|
417
|
+
debug: bool = False,
|
418
|
+
) -> Dict[str, Any]:
|
418
419
|
"""Get a Pipe's attributes from the API
|
419
420
|
|
420
421
|
Parameters
|
@@ -437,12 +438,12 @@ def get_pipe_attributes(
|
|
437
438
|
|
438
439
|
|
439
440
|
def get_sync_time(
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
441
|
+
self,
|
442
|
+
pipe: 'meerschaum.Pipe',
|
443
|
+
params: Optional[Dict[str, Any]] = None,
|
444
|
+
newest: bool = True,
|
445
|
+
debug: bool = False,
|
446
|
+
) -> Union[datetime, int, None]:
|
446
447
|
"""Get a Pipe's most recent datetime value from the API.
|
447
448
|
|
448
449
|
Parameters
|
@@ -492,10 +493,10 @@ def get_sync_time(
|
|
492
493
|
|
493
494
|
|
494
495
|
def pipe_exists(
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
496
|
+
self,
|
497
|
+
pipe: mrsm.Pipe,
|
498
|
+
debug: bool = False
|
499
|
+
) -> bool:
|
499
500
|
"""Check the API to see if a Pipe exists.
|
500
501
|
|
501
502
|
Parameters
|
@@ -523,9 +524,9 @@ def pipe_exists(
|
|
523
524
|
|
524
525
|
|
525
526
|
def create_metadata(
|
526
|
-
|
527
|
-
|
528
|
-
|
527
|
+
self,
|
528
|
+
debug: bool = False
|
529
|
+
) -> bool:
|
529
530
|
"""Create metadata tables.
|
530
531
|
|
531
532
|
Returns
|
@@ -547,14 +548,14 @@ def create_metadata(
|
|
547
548
|
|
548
549
|
|
549
550
|
def get_pipe_rowcount(
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
551
|
+
self,
|
552
|
+
pipe: mrsm.Pipe,
|
553
|
+
begin: Optional[datetime] = None,
|
554
|
+
end: Optional[datetime] = None,
|
555
|
+
params: Optional[Dict[str, Any]] = None,
|
556
|
+
remote: bool = False,
|
557
|
+
debug: bool = False,
|
558
|
+
) -> int:
|
558
559
|
"""Get a pipe's row count from the API.
|
559
560
|
|
560
561
|
Parameters
|
@@ -600,10 +601,10 @@ def get_pipe_rowcount(
|
|
600
601
|
|
601
602
|
|
602
603
|
def drop_pipe(
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
604
|
+
self,
|
605
|
+
pipe: mrsm.Pipe,
|
606
|
+
debug: bool = False
|
607
|
+
) -> SuccessTuple:
|
607
608
|
"""
|
608
609
|
Drop a pipe's table but maintain its registration.
|
609
610
|
|
@@ -644,11 +645,11 @@ def drop_pipe(
|
|
644
645
|
|
645
646
|
|
646
647
|
def clear_pipe(
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
648
|
+
self,
|
649
|
+
pipe: mrsm.Pipe,
|
650
|
+
debug: bool = False,
|
651
|
+
**kw
|
652
|
+
) -> SuccessTuple:
|
652
653
|
"""
|
653
654
|
Delete rows in a pipe's table.
|
654
655
|
|
@@ -666,7 +667,7 @@ def clear_pipe(
|
|
666
667
|
kw.pop('location_keys', None)
|
667
668
|
kw.pop('action', None)
|
668
669
|
kw.pop('force', None)
|
669
|
-
return self.
|
670
|
+
return self.do_action_legacy(
|
670
671
|
['clear', 'pipes'],
|
671
672
|
connector_keys = pipe.connector_keys,
|
672
673
|
metric_keys = pipe.metric_key,
|
@@ -678,10 +679,10 @@ def clear_pipe(
|
|
678
679
|
|
679
680
|
|
680
681
|
def get_pipe_columns_types(
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
682
|
+
self,
|
683
|
+
pipe: mrsm.Pipe,
|
684
|
+
debug: bool = False,
|
685
|
+
) -> Union[Dict[str, str], None]:
|
685
686
|
"""
|
686
687
|
Fetch the columns and types of the pipe's table.
|
687
688
|
|
meerschaum/jobs/_Job.py
CHANGED
@@ -62,8 +62,9 @@ class Job:
|
|
62
62
|
_properties: Optional[Dict[str, Any]] = None,
|
63
63
|
_rotating_log = None,
|
64
64
|
_stdin_file = None,
|
65
|
-
_status_hook = None,
|
66
|
-
_result_hook = None,
|
65
|
+
_status_hook: Optional[Callable[[], str]] = None,
|
66
|
+
_result_hook: Optional[Callable[[], SuccessTuple]] = None,
|
67
|
+
_externally_managed: bool = False,
|
67
68
|
):
|
68
69
|
"""
|
69
70
|
Create a new job to manage a `meerschaum.utils.daemon.Daemon`.
|
@@ -133,7 +134,10 @@ class Job:
|
|
133
134
|
if _result_hook is not None:
|
134
135
|
self._result_hook = _result_hook
|
135
136
|
|
137
|
+
self._externally_managed = _externally_managed
|
136
138
|
self._properties_patch = _properties or {}
|
139
|
+
if _externally_managed:
|
140
|
+
self._properties_patch.update({'externally_managed': _externally_managed})
|
137
141
|
|
138
142
|
daemon_sysargs = (
|
139
143
|
self._daemon.properties.get('target', {}).get('args', [None])[0]
|
@@ -154,9 +158,6 @@ class Job:
|
|
154
158
|
self._properties_patch.update({'restart': True})
|
155
159
|
break
|
156
160
|
|
157
|
-
if '--systemd' in self._sysargs:
|
158
|
-
self._properties_patch.update({'systemd': True})
|
159
|
-
|
160
161
|
@staticmethod
|
161
162
|
def from_pid(pid: int, executor_keys: Optional[str] = None) -> Job:
|
162
163
|
"""
|
@@ -824,7 +825,11 @@ class Job:
|
|
824
825
|
"""
|
825
826
|
Return a bool indicating whether this job should be displayed.
|
826
827
|
"""
|
827
|
-
return
|
828
|
+
return (
|
829
|
+
self.name.startswith('_')
|
830
|
+
or self.name.startswith('.')
|
831
|
+
or self._is_externally_managed
|
832
|
+
)
|
828
833
|
|
829
834
|
def check_restart(self) -> SuccessTuple:
|
830
835
|
"""
|
@@ -850,6 +855,33 @@ class Job:
|
|
850
855
|
"""
|
851
856
|
return shlex.join(self.sysargs).replace(' + ', '\n+ ')
|
852
857
|
|
858
|
+
@property
|
859
|
+
def _externally_managed_file(self) -> pathlib.Path:
|
860
|
+
"""
|
861
|
+
Return the path to the externally managed file.
|
862
|
+
"""
|
863
|
+
return self.daemon.path / '.externally-managed'
|
864
|
+
|
865
|
+
def _set_externally_managed(self):
|
866
|
+
"""
|
867
|
+
Set this job as externally managed.
|
868
|
+
"""
|
869
|
+
self._externally_managed = True
|
870
|
+
try:
|
871
|
+
self._externally_managed_file.parent.mkdir(exist_ok=True, parents=True)
|
872
|
+
self._externally_managed_file.touch()
|
873
|
+
except Exception as e:
|
874
|
+
warn(e)
|
875
|
+
|
876
|
+
@property
|
877
|
+
def _is_externally_managed(self) -> bool:
|
878
|
+
"""
|
879
|
+
Return whether this job is externally managed.
|
880
|
+
"""
|
881
|
+
return self.executor_keys in (None, 'local') and (
|
882
|
+
self._externally_managed or self._externally_managed_file.exists()
|
883
|
+
)
|
884
|
+
|
853
885
|
def __str__(self) -> str:
|
854
886
|
sysargs = self.sysargs
|
855
887
|
sysargs_str = shlex.join(sysargs) if sysargs else ''
|
meerschaum/jobs/__init__.py
CHANGED
@@ -16,6 +16,7 @@ from meerschaum.jobs._Executor import Executor
|
|
16
16
|
|
17
17
|
__all__ = (
|
18
18
|
'Job',
|
19
|
+
'systemd',
|
19
20
|
'get_jobs',
|
20
21
|
'get_filtered_jobs',
|
21
22
|
'get_restart_jobs',
|
@@ -23,8 +24,8 @@ __all__ = (
|
|
23
24
|
'get_stopped_jobs',
|
24
25
|
'get_paused_jobs',
|
25
26
|
'get_restart_jobs',
|
26
|
-
'Executor',
|
27
27
|
'make_executor',
|
28
|
+
'Executor',
|
28
29
|
'check_restart_jobs',
|
29
30
|
'start_check_jobs_thread',
|
30
31
|
'stop_check_jobs_thread',
|
@@ -72,7 +73,8 @@ def get_jobs(
|
|
72
73
|
return {
|
73
74
|
name: job
|
74
75
|
for name, job in jobs.items()
|
75
|
-
if include_hidden or not job.hidden
|
76
|
+
if (include_hidden or not job.hidden) and not job._is_externally_managed
|
77
|
+
|
76
78
|
}
|
77
79
|
|
78
80
|
def _get_systemd_jobs():
|
@@ -387,7 +389,7 @@ def _install_healthcheck_job() -> SuccessTuple:
|
|
387
389
|
return False, "Not running systemd."
|
388
390
|
|
389
391
|
job = Job(
|
390
|
-
'.
|
392
|
+
'.local-healthcheck',
|
391
393
|
['restart', 'jobs', '-e', 'local', '--loop'],
|
392
394
|
executor_keys='systemd',
|
393
395
|
)
|
@@ -13,6 +13,7 @@ import asyncio
|
|
13
13
|
import json
|
14
14
|
import time
|
15
15
|
import traceback
|
16
|
+
import shutil
|
16
17
|
from datetime import datetime, timezone
|
17
18
|
from functools import partial
|
18
19
|
|
@@ -37,10 +38,10 @@ class SystemdExecutor(Executor):
|
|
37
38
|
"""
|
38
39
|
Return a list of existing jobs, including hidden ones.
|
39
40
|
"""
|
40
|
-
from meerschaum.config.paths import
|
41
|
+
from meerschaum.config.paths import SYSTEMD_USER_RESOURCES_PATH
|
41
42
|
return [
|
42
43
|
service_name[len('mrsm-'):(-1 * len('.service'))]
|
43
|
-
for service_name in os.listdir(
|
44
|
+
for service_name in os.listdir(SYSTEMD_USER_RESOURCES_PATH)
|
44
45
|
if service_name.startswith('mrsm-') and service_name.endswith('.service')
|
45
46
|
]
|
46
47
|
|
@@ -73,6 +74,13 @@ class SystemdExecutor(Executor):
|
|
73
74
|
"""
|
74
75
|
return f"mrsm-{name.replace(' ', '-')}.service"
|
75
76
|
|
77
|
+
def get_service_job_path(self, name: str, debug: bool = False) -> pathlib.Path:
|
78
|
+
"""
|
79
|
+
Return the path for the job's files under the root directory.
|
80
|
+
"""
|
81
|
+
from meerschaum.config.paths import SYSTEMD_JOBS_RESOURCES_PATH
|
82
|
+
return SYSTEMD_JOBS_RESOURCES_PATH / name
|
83
|
+
|
76
84
|
def get_service_symlink_file_path(self, name: str, debug: bool = False) -> pathlib.Path:
|
77
85
|
"""
|
78
86
|
Return the path to where to create the service symlink.
|
@@ -84,8 +92,10 @@ class SystemdExecutor(Executor):
|
|
84
92
|
"""
|
85
93
|
Return the path to a Job's service file.
|
86
94
|
"""
|
87
|
-
|
88
|
-
|
95
|
+
return (
|
96
|
+
self.get_service_job_path(name, debug=debug)
|
97
|
+
/ self.get_service_name(name, debug=debug)
|
98
|
+
)
|
89
99
|
|
90
100
|
def get_service_logs_path(self, name: str, debug: bool = False) -> pathlib.Path:
|
91
101
|
"""
|
@@ -94,29 +104,22 @@ class SystemdExecutor(Executor):
|
|
94
104
|
from meerschaum.config.paths import SYSTEMD_LOGS_RESOURCES_PATH
|
95
105
|
return SYSTEMD_LOGS_RESOURCES_PATH / (self.get_service_name(name, debug=debug) + '.log')
|
96
106
|
|
97
|
-
def get_service_socket_path(self, name: str, debug: bool = False) -> pathlib.Path:
|
98
|
-
"""
|
99
|
-
Return the path to the unit file for the socket (not the socket itself).
|
100
|
-
"""
|
101
|
-
from meerschaum.config.paths import SYSTEMD_USER_RESOURCES_PATH
|
102
|
-
return SYSTEMD_USER_RESOURCES_PATH / (
|
103
|
-
self.get_service_name(name, debug=debug).replace('.service', '.socket')
|
104
|
-
)
|
105
|
-
|
106
107
|
def get_socket_path(self, name: str, debug: bool = False) -> pathlib.Path:
|
107
108
|
"""
|
108
109
|
Return the path to the FIFO file.
|
109
110
|
"""
|
110
|
-
|
111
|
-
|
111
|
+
return (
|
112
|
+
self.get_service_job_path(name, debug=debug)
|
113
|
+
/ (self.get_service_name(name, debug=debug) + '.stdin')
|
114
|
+
)
|
112
115
|
|
113
116
|
def get_result_path(self, name: str, debug: bool = False) -> pathlib.Path:
|
114
117
|
"""
|
115
118
|
Return the path to the result file.
|
116
119
|
"""
|
117
|
-
|
118
|
-
|
119
|
-
self.get_service_name(name, debug=debug) + '.result.json'
|
120
|
+
return (
|
121
|
+
self.get_service_job_path(name, debug=debug)
|
122
|
+
/ (self.get_service_name(name, debug=debug) + '.result.json')
|
120
123
|
)
|
121
124
|
|
122
125
|
def get_service_file_text(self, name: str, sysargs: List[str], debug: bool = False) -> str:
|
@@ -191,17 +194,19 @@ class SystemdExecutor(Executor):
|
|
191
194
|
"""
|
192
195
|
Return the hidden "sister" job to store a job's parameters.
|
193
196
|
"""
|
194
|
-
|
195
|
-
|
196
|
-
return Job(
|
197
|
-
hidden_name,
|
197
|
+
job = Job(
|
198
|
+
name,
|
198
199
|
sysargs,
|
199
200
|
executor_keys='local',
|
200
201
|
_rotating_log=self.get_job_rotating_file(name, debug=debug),
|
201
202
|
_stdin_file=self.get_job_stdin_file(name, debug=debug),
|
202
203
|
_status_hook=partial(self.get_job_status, name),
|
203
204
|
_result_hook=partial(self.get_job_result, name),
|
205
|
+
_externally_managed=True,
|
204
206
|
)
|
207
|
+
job._set_externally_managed()
|
208
|
+
return job
|
209
|
+
|
205
210
|
|
206
211
|
def get_job_metadata(self, name: str, debug: bool = False) -> Dict[str, Any]:
|
207
212
|
"""
|
@@ -489,6 +494,7 @@ class SystemdExecutor(Executor):
|
|
489
494
|
|
490
495
|
if name not in self._stdin_files:
|
491
496
|
socket_path = self.get_socket_path(name, debug=debug)
|
497
|
+
socket_path.parent.mkdir(parents=True, exist_ok=True)
|
492
498
|
self._stdin_files[name] = StdinFile(socket_path)
|
493
499
|
|
494
500
|
return self._stdin_files[name]
|
@@ -504,6 +510,9 @@ class SystemdExecutor(Executor):
|
|
504
510
|
socket_stdin = self.get_job_stdin_file(name, debug=debug)
|
505
511
|
_ = socket_stdin.file_handler
|
506
512
|
|
513
|
+
### Init the `externally_managed file`.
|
514
|
+
_ = self.get_hidden_job(name, debug=debug)
|
515
|
+
|
507
516
|
with open(service_file_path, 'w+', encoding='utf-8') as f:
|
508
517
|
f.write(self.get_service_file_text(name, sysargs, debug=debug))
|
509
518
|
|
@@ -594,6 +603,14 @@ class SystemdExecutor(Executor):
|
|
594
603
|
debug=debug,
|
595
604
|
)
|
596
605
|
|
606
|
+
service_job_path = self.get_service_job_path(name, debug=debug)
|
607
|
+
try:
|
608
|
+
if service_job_path.exists():
|
609
|
+
shutil.rmtree(service_job_path)
|
610
|
+
except Exception as e:
|
611
|
+
warn(e)
|
612
|
+
return False, str(e)
|
613
|
+
|
597
614
|
service_logs_path = self.get_service_logs_path(name, debug=debug)
|
598
615
|
logs_paths = [
|
599
616
|
(SYSTEMD_LOGS_RESOURCES_PATH / name)
|
meerschaum/plugins/_Plugin.py
CHANGED
@@ -654,7 +654,7 @@ class Plugin:
|
|
654
654
|
import ast, re
|
655
655
|
### NOTE: This technically would break
|
656
656
|
### if `required` was the very first line of the file.
|
657
|
-
req_start_match = re.search(r'
|
657
|
+
req_start_match = re.search(r'\nrequired(:\s*)?.*=', text)
|
658
658
|
if not req_start_match:
|
659
659
|
return []
|
660
660
|
req_start = req_start_match.start()
|
meerschaum/plugins/__init__.py
CHANGED
@@ -28,7 +28,8 @@ _locks = {
|
|
28
28
|
'PLUGINS_INTERNAL_LOCK_PATH': RLock(),
|
29
29
|
}
|
30
30
|
__all__ = (
|
31
|
-
"Plugin", "make_action", "api_plugin", "dash_plugin", "
|
31
|
+
"Plugin", "make_action", "api_plugin", "dash_plugin", "web_page",
|
32
|
+
"import_plugins", "from_plugin_import",
|
32
33
|
"reload_plugins", "get_plugins", "get_data_plugins", "add_plugin_argument",
|
33
34
|
"pre_sync_hook", "post_sync_hook",
|
34
35
|
)
|
@@ -50,6 +50,7 @@ class StdinFile(io.TextIOBase):
|
|
50
50
|
if self.file_path.exists():
|
51
51
|
self.file_path.unlink()
|
52
52
|
|
53
|
+
self.file_path.parent.mkdir(parents=True, exist_ok=True)
|
53
54
|
os.mkfifo(self.file_path.as_posix(), mode=0o600)
|
54
55
|
|
55
56
|
self._fd = os.open(self.file_path, os.O_RDONLY | os.O_NONBLOCK)
|
@@ -18,7 +18,8 @@ _bank: Dict[str, Dict[str, List[str]]] = {
|
|
18
18
|
'bright', 'dark', 'neon',
|
19
19
|
],
|
20
20
|
'sizes': [
|
21
|
-
'big', 'small', 'large', 'huge', 'tiny', 'long', 'short', '
|
21
|
+
'big', 'small', 'large', 'huge', 'tiny', 'long', 'short', 'average', 'mini', 'micro',
|
22
|
+
'maximum', 'minimum', 'median',
|
22
23
|
],
|
23
24
|
'personalities': [
|
24
25
|
'groovy', 'cool', 'awesome', 'nice', 'fantastic', 'sweet', 'great', 'amazing',
|
@@ -26,29 +27,36 @@ _bank: Dict[str, Dict[str, List[str]]] = {
|
|
26
27
|
],
|
27
28
|
'emotions': [
|
28
29
|
'angry', 'happy', 'excited', 'suspicious', 'sad', 'thankful', 'grateful', 'satisfied',
|
30
|
+
'peaceful', 'ferocious', 'content',
|
29
31
|
],
|
30
32
|
'sensations': [
|
31
33
|
'sleepy', 'awake', 'alert', 'thirsty', 'comfy', 'warm', 'cold', 'chilly', 'soft',
|
32
|
-
'smooth', 'chunky',
|
34
|
+
'smooth', 'chunky', 'hungry',
|
33
35
|
],
|
34
36
|
'materials': [
|
35
37
|
'golden', 'silver', 'metal', 'plastic', 'wool', 'wooden', 'nylon', 'fuzzy', 'silky',
|
38
|
+
'suede', 'vinyl',
|
36
39
|
],
|
37
40
|
'qualities': [
|
38
41
|
'expensive', 'cheap', 'premier', 'best', 'favorite', 'better', 'good', 'affordable',
|
42
|
+
'organic', 'electric',
|
39
43
|
],
|
40
44
|
},
|
41
45
|
'nouns' : {
|
42
46
|
'animals': [
|
43
|
-
'mouse', 'fox', 'horse', '
|
47
|
+
'mouse', 'fox', 'horse', 'pig', 'hippo', 'elephant' , 'tiger', 'deer', 'salmon',
|
44
48
|
'gerbil', 'snake', 'turtle', 'rhino', 'dog', 'cat', 'giraffe', 'rabbit', 'squirrel',
|
45
49
|
'unicorn', 'lizard', 'lion', 'bear', 'gazelle', 'whale', 'dolphin', 'fish', 'butterfly',
|
46
50
|
'ladybug', 'fly', 'shrimp', 'flamingo', 'parrot', 'tuna', 'panda', 'lemur', 'duck',
|
47
51
|
'seal', 'walrus', 'seagull', 'iguana', 'salamander', 'kitten', 'puppy', 'octopus',
|
48
52
|
],
|
53
|
+
'weather': [
|
54
|
+
'rain', 'sun', 'snow', 'wind', 'tornado', 'hurricane', 'blizzard', 'monsoon', 'storm',
|
55
|
+
'shower', 'hail',
|
56
|
+
],
|
49
57
|
'plants': [
|
50
58
|
'tree', 'flower', 'vine', 'fern', 'palm', 'palmetto', 'oak', 'pine', 'rose', 'lily',
|
51
|
-
'ivy',
|
59
|
+
'ivy', 'leaf', 'shrubbery', 'acorn', 'fruit',
|
52
60
|
],
|
53
61
|
'foods': [
|
54
62
|
'pizza', 'sushi', 'apple', 'banana', 'sandwich', 'burger', 'taco', 'bratwurst',
|
@@ -74,8 +82,6 @@ _bank: Dict[str, Dict[str, List[str]]] = {
|
|
74
82
|
},
|
75
83
|
}
|
76
84
|
|
77
|
-
_disallow_combinations: List[Tuple[str, str]] = []
|
78
|
-
|
79
85
|
_adjectives: List[str]= []
|
80
86
|
for category, items in _bank['adjectives'].items():
|
81
87
|
_adjectives += items
|
@@ -96,12 +102,8 @@ def generate_random_name(separator: str = '-'):
|
|
96
102
|
-------
|
97
103
|
A string containing an random adjective and random noun.
|
98
104
|
"""
|
99
|
-
|
100
|
-
|
101
|
-
noun_category = random.choice(list(_bank['nouns'].keys()))
|
102
|
-
if (adjective_category, noun_category) in _disallow_combinations:
|
103
|
-
continue
|
104
|
-
break
|
105
|
+
adjective_category = random.choice(list(_bank['adjectives'].keys()))
|
106
|
+
noun_category = random.choice(list(_bank['nouns'].keys()))
|
105
107
|
return (
|
106
108
|
random.choice(_bank['adjectives'][adjective_category])
|
107
109
|
+ separator
|