ominfra 0.0.0.dev127__py3-none-any.whl → 0.0.0.dev128__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.
- ominfra/scripts/supervisor.py +723 -731
- ominfra/supervisor/configs.py +34 -11
- ominfra/supervisor/context.py +5 -9
- ominfra/supervisor/dispatchers.py +4 -3
- ominfra/supervisor/dispatchersimpl.py +10 -9
- ominfra/supervisor/groups.py +1 -1
- ominfra/supervisor/inject.py +5 -5
- ominfra/supervisor/main.py +2 -2
- ominfra/supervisor/pipes.py +15 -13
- ominfra/supervisor/poller.py +36 -35
- ominfra/supervisor/{processes.py → process.py} +2 -1
- ominfra/supervisor/{processesimpl.py → processimpl.py} +35 -40
- ominfra/supervisor/setup.py +1 -1
- ominfra/supervisor/setupimpl.py +4 -3
- ominfra/supervisor/spawning.py +2 -1
- ominfra/supervisor/spawningimpl.py +15 -12
- ominfra/supervisor/supervisor.py +16 -8
- ominfra/supervisor/types.py +7 -9
- ominfra/supervisor/utils/__init__.py +0 -0
- ominfra/supervisor/utils/diag.py +31 -0
- ominfra/supervisor/utils/fds.py +46 -0
- ominfra/supervisor/utils/fs.py +47 -0
- ominfra/supervisor/utils/os.py +45 -0
- ominfra/supervisor/utils/ostypes.py +9 -0
- ominfra/supervisor/utils/strings.py +105 -0
- ominfra/supervisor/{users.py → utils/users.py} +11 -8
- {ominfra-0.0.0.dev127.dist-info → ominfra-0.0.0.dev128.dist-info}/METADATA +3 -3
- {ominfra-0.0.0.dev127.dist-info → ominfra-0.0.0.dev128.dist-info}/RECORD +34 -29
- ominfra/supervisor/datatypes.py +0 -113
- ominfra/supervisor/utils.py +0 -206
- /ominfra/supervisor/{collections.py → utils/collections.py} +0 -0
- /ominfra/supervisor/{signals.py → utils/signals.py} +0 -0
- {ominfra-0.0.0.dev127.dist-info → ominfra-0.0.0.dev128.dist-info}/LICENSE +0 -0
- {ominfra-0.0.0.dev127.dist-info → ominfra-0.0.0.dev128.dist-info}/WHEEL +0 -0
- {ominfra-0.0.0.dev127.dist-info → ominfra-0.0.0.dev128.dist-info}/entry_points.txt +0 -0
- {ominfra-0.0.0.dev127.dist-info → ominfra-0.0.0.dev128.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,105 @@
|
|
1
|
+
# ruff: noqa: UP006 UP007
|
2
|
+
import typing as ta
|
3
|
+
|
4
|
+
|
5
|
+
##
|
6
|
+
|
7
|
+
|
8
|
+
def as_bytes(s: ta.Union[str, bytes], encoding: str = 'utf8') -> bytes:
|
9
|
+
if isinstance(s, bytes):
|
10
|
+
return s
|
11
|
+
else:
|
12
|
+
return s.encode(encoding)
|
13
|
+
|
14
|
+
|
15
|
+
@ta.overload
|
16
|
+
def find_prefix_at_end(haystack: str, needle: str) -> int:
|
17
|
+
...
|
18
|
+
|
19
|
+
|
20
|
+
@ta.overload
|
21
|
+
def find_prefix_at_end(haystack: bytes, needle: bytes) -> int:
|
22
|
+
...
|
23
|
+
|
24
|
+
|
25
|
+
def find_prefix_at_end(haystack, needle):
|
26
|
+
l = len(needle) - 1
|
27
|
+
while l and not haystack.endswith(needle[:l]):
|
28
|
+
l -= 1
|
29
|
+
return l
|
30
|
+
|
31
|
+
|
32
|
+
##
|
33
|
+
|
34
|
+
|
35
|
+
ANSI_ESCAPE_BEGIN = b'\x1b['
|
36
|
+
ANSI_TERMINATORS = (b'H', b'f', b'A', b'B', b'C', b'D', b'R', b's', b'u', b'J', b'K', b'h', b'l', b'p', b'm')
|
37
|
+
|
38
|
+
|
39
|
+
def strip_escapes(s: bytes) -> bytes:
|
40
|
+
"""Remove all ANSI color escapes from the given string."""
|
41
|
+
|
42
|
+
result = b''
|
43
|
+
show = 1
|
44
|
+
i = 0
|
45
|
+
l = len(s)
|
46
|
+
while i < l:
|
47
|
+
if show == 0 and s[i:i + 1] in ANSI_TERMINATORS:
|
48
|
+
show = 1
|
49
|
+
elif show:
|
50
|
+
n = s.find(ANSI_ESCAPE_BEGIN, i)
|
51
|
+
if n == -1:
|
52
|
+
return result + s[i:]
|
53
|
+
else:
|
54
|
+
result = result + s[i:n]
|
55
|
+
i = n
|
56
|
+
show = 0
|
57
|
+
i += 1
|
58
|
+
return result
|
59
|
+
|
60
|
+
|
61
|
+
##
|
62
|
+
|
63
|
+
|
64
|
+
class SuffixMultiplier:
|
65
|
+
# d is a dictionary of suffixes to integer multipliers. If no suffixes match, default is the multiplier. Matches
|
66
|
+
# are case insensitive. Return values are in the fundamental unit.
|
67
|
+
def __init__(self, d, default=1):
|
68
|
+
super().__init__()
|
69
|
+
self._d = d
|
70
|
+
self._default = default
|
71
|
+
# all keys must be the same size
|
72
|
+
self._keysz = None
|
73
|
+
for k in d:
|
74
|
+
if self._keysz is None:
|
75
|
+
self._keysz = len(k)
|
76
|
+
elif self._keysz != len(k): # type: ignore
|
77
|
+
raise ValueError(k)
|
78
|
+
|
79
|
+
def __call__(self, v: ta.Union[str, int]) -> int:
|
80
|
+
if isinstance(v, int):
|
81
|
+
return v
|
82
|
+
v = v.lower()
|
83
|
+
for s, m in self._d.items():
|
84
|
+
if v[-self._keysz:] == s: # type: ignore
|
85
|
+
return int(v[:-self._keysz]) * m # type: ignore
|
86
|
+
return int(v) * self._default
|
87
|
+
|
88
|
+
|
89
|
+
parse_bytes_size = SuffixMultiplier({
|
90
|
+
'kb': 1024,
|
91
|
+
'mb': 1024 * 1024,
|
92
|
+
'gb': 1024 * 1024 * 1024,
|
93
|
+
})
|
94
|
+
|
95
|
+
|
96
|
+
#
|
97
|
+
|
98
|
+
|
99
|
+
def parse_octal(arg: ta.Union[str, int]) -> int:
|
100
|
+
if isinstance(arg, int):
|
101
|
+
return arg
|
102
|
+
try:
|
103
|
+
return int(arg, 8)
|
104
|
+
except (TypeError, ValueError):
|
105
|
+
raise ValueError(f'{arg} can not be converted to an octal type') # noqa
|
@@ -3,11 +3,14 @@ import dataclasses as dc
|
|
3
3
|
import grp
|
4
4
|
import pwd
|
5
5
|
|
6
|
+
from .ostypes import Gid
|
7
|
+
from .ostypes import Uid
|
8
|
+
|
6
9
|
|
7
10
|
##
|
8
11
|
|
9
12
|
|
10
|
-
def name_to_uid(name: str) ->
|
13
|
+
def name_to_uid(name: str) -> Uid:
|
11
14
|
try:
|
12
15
|
uid = int(name)
|
13
16
|
except ValueError:
|
@@ -21,10 +24,10 @@ def name_to_uid(name: str) -> int:
|
|
21
24
|
pwd.getpwuid(uid) # check if uid is valid
|
22
25
|
except KeyError:
|
23
26
|
raise ValueError(f'Invalid user id {name}') # noqa
|
24
|
-
return uid
|
27
|
+
return Uid(uid)
|
25
28
|
|
26
29
|
|
27
|
-
def name_to_gid(name: str) ->
|
30
|
+
def name_to_gid(name: str) -> Gid:
|
28
31
|
try:
|
29
32
|
gid = int(name)
|
30
33
|
except ValueError:
|
@@ -38,12 +41,12 @@ def name_to_gid(name: str) -> int:
|
|
38
41
|
grp.getgrgid(gid) # check if gid is valid
|
39
42
|
except KeyError:
|
40
43
|
raise ValueError(f'Invalid group id {name}') # noqa
|
41
|
-
return gid
|
44
|
+
return Gid(gid)
|
42
45
|
|
43
46
|
|
44
|
-
def gid_for_uid(uid:
|
47
|
+
def gid_for_uid(uid: Uid) -> Gid:
|
45
48
|
pwrec = pwd.getpwuid(uid)
|
46
|
-
return pwrec[3]
|
49
|
+
return Gid(pwrec[3])
|
47
50
|
|
48
51
|
|
49
52
|
##
|
@@ -52,8 +55,8 @@ def gid_for_uid(uid: int) -> int:
|
|
52
55
|
@dc.dataclass(frozen=True)
|
53
56
|
class User:
|
54
57
|
name: str
|
55
|
-
uid:
|
56
|
-
gid:
|
58
|
+
uid: Uid
|
59
|
+
gid: Gid
|
57
60
|
|
58
61
|
|
59
62
|
def get_user(name: str) -> User:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: ominfra
|
3
|
-
Version: 0.0.0.
|
3
|
+
Version: 0.0.0.dev128
|
4
4
|
Summary: ominfra
|
5
5
|
Author: wrmsr
|
6
6
|
License: BSD-3-Clause
|
@@ -12,8 +12,8 @@ Classifier: Operating System :: OS Independent
|
|
12
12
|
Classifier: Operating System :: POSIX
|
13
13
|
Requires-Python: >=3.12
|
14
14
|
License-File: LICENSE
|
15
|
-
Requires-Dist: omdev==0.0.0.
|
16
|
-
Requires-Dist: omlish==0.0.0.
|
15
|
+
Requires-Dist: omdev==0.0.0.dev128
|
16
|
+
Requires-Dist: omlish==0.0.0.dev128
|
17
17
|
Provides-Extra: all
|
18
18
|
Requires-Dist: paramiko~=3.5; extra == "all"
|
19
19
|
Requires-Dist: asyncssh~=2.18; extra == "all"
|
@@ -61,45 +61,50 @@ ominfra/pyremote/bootstrap.py,sha256=RvMO3YGaN1E4sgUi1JEtiPak8cjvqtc_vRCq1yqbeZg
|
|
61
61
|
ominfra/pyremote/runcommands.py,sha256=bviS0_TDIoZVAe4h-_iavbvJtVSFu8lnk7fQ5iasCWE,1571
|
62
62
|
ominfra/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
63
63
|
ominfra/scripts/journald2aws.py,sha256=UpwV8P1ZE8ywXW-8xpCaTCBRWe94BuG_MS1CXfD3wcw,128547
|
64
|
-
ominfra/scripts/supervisor.py,sha256=
|
64
|
+
ominfra/scripts/supervisor.py,sha256=ZqUDlxRxSML5Ty0sOKuils35km5-9xjYBQF4yQDnVaY,222164
|
65
65
|
ominfra/supervisor/LICENSE.txt,sha256=yvqaMNsDhWxziHa9ien6qCW1SkZv-DQlAg96XjfSee8,1746
|
66
66
|
ominfra/supervisor/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
|
67
67
|
ominfra/supervisor/__main__.py,sha256=I0yFw-C08OOiZ3BF6lF1Oiv789EQXu-_j6whDhQUTEA,66
|
68
|
-
ominfra/supervisor/
|
69
|
-
ominfra/supervisor/
|
70
|
-
ominfra/supervisor/
|
71
|
-
ominfra/supervisor/
|
72
|
-
ominfra/supervisor/dispatchers.py,sha256=nbgTaWrRxBvVfJSBsf2wnL4hTAG63PETXXpFaol6VCw,936
|
73
|
-
ominfra/supervisor/dispatchersimpl.py,sha256=Shey0RVWxX1cgShEIlOsM3iJY5LAmayigi9sNnu4fQc,10897
|
68
|
+
ominfra/supervisor/configs.py,sha256=AhBlbifwDXc0acEhcbdv9jphJL-SBFODFDAWDVckzAE,3945
|
69
|
+
ominfra/supervisor/context.py,sha256=UDJc0mVHHFg3T7MyO7gehWX1wwmFvw-7xeKLl-cC8jc,2595
|
70
|
+
ominfra/supervisor/dispatchers.py,sha256=qWtVLx-4H3I-Io7OPcVgRpIYehGsA4q3Duo5ZWdUM4Y,970
|
71
|
+
ominfra/supervisor/dispatchersimpl.py,sha256=t1VFcofj1kTH1q13Z-S1OUTXixPwgSqJkh5A5IkHKPA,10956
|
74
72
|
ominfra/supervisor/events.py,sha256=w3HQFrq-SuroYWoQfNFYeU1phnTvHTgsAqA6TGtAafI,6593
|
75
73
|
ominfra/supervisor/exceptions.py,sha256=Qbu211H3CLlSmi9LsSikOwrcL5HgJP9ugvcKWlGTAoI,750
|
76
|
-
ominfra/supervisor/groups.py,sha256=
|
74
|
+
ominfra/supervisor/groups.py,sha256=g5Zp_lkVhn1FSe6GSEPbaELincG5a46ctv1xpB-WmnQ,2163
|
77
75
|
ominfra/supervisor/groupsimpl.py,sha256=_5Mxf6VdVV375KgwcuUTpErUH4FBpmzbNm3vbGB_JaQ,2304
|
78
|
-
ominfra/supervisor/inject.py,sha256=
|
79
|
-
ominfra/supervisor/main.py,sha256=
|
80
|
-
ominfra/supervisor/pipes.py,sha256=
|
81
|
-
ominfra/supervisor/poller.py,sha256=
|
76
|
+
ominfra/supervisor/inject.py,sha256=ZCfloXxURjiVTutzudGFWybrVCvjDD_C3HayMATCMrY,3042
|
77
|
+
ominfra/supervisor/main.py,sha256=RCCpMX4D2RKT8vZMF82pENKpXfW3GUdNgMEUzUtpqL0,4140
|
78
|
+
ominfra/supervisor/pipes.py,sha256=XrJ9lD04tPdzZD3xhhYKxpBKHWhZ0Ii315E78bgj7ws,2233
|
79
|
+
ominfra/supervisor/poller.py,sha256=LnQVttPCm8a1UtnDvsho6zLw8NP-2_2VUiNM-d0w_FU,7776
|
82
80
|
ominfra/supervisor/privileges.py,sha256=bO7rJGT7cMOBALK_4D4NiQnOS5dOYb14Sz66R-ymG24,2071
|
83
|
-
ominfra/supervisor/
|
84
|
-
ominfra/supervisor/
|
85
|
-
ominfra/supervisor/setup.py,sha256=
|
86
|
-
ominfra/supervisor/setupimpl.py,sha256=
|
87
|
-
ominfra/supervisor/
|
88
|
-
ominfra/supervisor/
|
89
|
-
ominfra/supervisor/spawningimpl.py,sha256=zaamb1aOsHv1QaV4Rh_e6LErUTwXJULcf_PGsrhNz_c,10941
|
81
|
+
ominfra/supervisor/process.py,sha256=UaubVxsxVqDnbuWVpTH0DTGbJGLO0vGJ9mNcvy2kCXM,217
|
82
|
+
ominfra/supervisor/processimpl.py,sha256=0i0P3gdxuJsgcvy2VTKN6-NYgcBjozUaPsA_tUcEmb4,18769
|
83
|
+
ominfra/supervisor/setup.py,sha256=7HwwwI-WT_Z0WjZ9_l5Orr4K298nKKhQ1f_ZgGsi9TU,622
|
84
|
+
ominfra/supervisor/setupimpl.py,sha256=S_YgCH3XzLsFIAriJROvDMUDh7OzVVJoxzEzCkbb4g4,9648
|
85
|
+
ominfra/supervisor/spawning.py,sha256=i1k3tmqWyU-KIN7kel-JVxTVGnLiTIVmZzlstJSZpjM,622
|
86
|
+
ominfra/supervisor/spawningimpl.py,sha256=0InDyRPh7gAEX07lg6eUYMymX0RikHOz_ieAghxKx8Y,11063
|
90
87
|
ominfra/supervisor/states.py,sha256=9yoNOSwalRcKEnCP9zG6tVS0oivo5tCeuH6AaaW7Jpc,890
|
91
|
-
ominfra/supervisor/supervisor.py,sha256=
|
92
|
-
ominfra/supervisor/types.py,sha256=
|
93
|
-
ominfra/supervisor/
|
94
|
-
ominfra/supervisor/utils.py,sha256=
|
88
|
+
ominfra/supervisor/supervisor.py,sha256=3yBaGJHJGqDXlARjpHWg7371N6jb29HaFEI-_fSp-xU,12028
|
89
|
+
ominfra/supervisor/types.py,sha256=i2C7ZBvLqjVliIYAYQnPx2WwIQ14HIVV1hTUgB2mbBM,4740
|
90
|
+
ominfra/supervisor/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
91
|
+
ominfra/supervisor/utils/collections.py,sha256=vcfmVYS4QngMdtEI1DvdRIcubmy55Wj40NCzW27_rIY,1361
|
92
|
+
ominfra/supervisor/utils/diag.py,sha256=ujz4gkW7p3wmbaKFM8Hz5eHEwpoUkbB8JeDvcHilCz0,705
|
93
|
+
ominfra/supervisor/utils/fds.py,sha256=lz8DWXzGYvu93dqhWK0WrhXrrJVQ_psoom4Nj_o8g2g,849
|
94
|
+
ominfra/supervisor/utils/fs.py,sha256=ABbNcsCpzSXAvq_ZZSCj61mj5kGnVuC4spUmoWenlqw,1155
|
95
|
+
ominfra/supervisor/utils/os.py,sha256=9fw--tpHOrSjGTCkUo1KRBgbGGxKW2va5xKw2cHwtRU,1096
|
96
|
+
ominfra/supervisor/utils/ostypes.py,sha256=B7VjwbzVesz9we9MztoSk8bH8sTxMIWtILy_Qde0G7w,164
|
97
|
+
ominfra/supervisor/utils/signals.py,sha256=uZkTvissbtq7TlJD4MkTiL3F-zyWmAFUuWQtFjsf0MI,1474
|
98
|
+
ominfra/supervisor/utils/strings.py,sha256=B0UOuVM_NIWmcznycmiEbwJ0lcoTGEd3Ir1AeLkBXeU,2478
|
99
|
+
ominfra/supervisor/utils/users.py,sha256=PRUhWy74WQCxix4BLNYcWW1i2mF1IyAxj1RzElnP4iM,1345
|
95
100
|
ominfra/tailscale/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
96
101
|
ominfra/tailscale/api.py,sha256=C5-t_b6jZXUWcy5k8bXm7CFnk73pSdrlMOgGDeGVrpw,1370
|
97
102
|
ominfra/tailscale/cli.py,sha256=DSGp4hn5xwOW-l_u_InKlSF6kIobxtUtVssf_73STs0,3567
|
98
103
|
ominfra/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
99
104
|
ominfra/tools/listresources.py,sha256=4qVg5txsb10EHhvqXXeM6gJ2jx9LbroEnPydDv1uXs0,6176
|
100
|
-
ominfra-0.0.0.
|
101
|
-
ominfra-0.0.0.
|
102
|
-
ominfra-0.0.0.
|
103
|
-
ominfra-0.0.0.
|
104
|
-
ominfra-0.0.0.
|
105
|
-
ominfra-0.0.0.
|
105
|
+
ominfra-0.0.0.dev128.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
|
106
|
+
ominfra-0.0.0.dev128.dist-info/METADATA,sha256=JV6Hw2ZOpDub73wDD4p69Qq9F6XbbKlthV7CmH6G_-k,731
|
107
|
+
ominfra-0.0.0.dev128.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
108
|
+
ominfra-0.0.0.dev128.dist-info/entry_points.txt,sha256=kgecQ2MgGrM9qK744BoKS3tMesaC3yjLnl9pa5CRczg,37
|
109
|
+
ominfra-0.0.0.dev128.dist-info/top_level.txt,sha256=E-b2OHkk_AOBLXHYZQ2EOFKl-_6uOGd8EjeG-Zy6h_w,8
|
110
|
+
ominfra-0.0.0.dev128.dist-info/RECORD,,
|
ominfra/supervisor/datatypes.py
DELETED
@@ -1,113 +0,0 @@
|
|
1
|
-
# ruff: noqa: UP007
|
2
|
-
import logging
|
3
|
-
import os
|
4
|
-
import typing as ta
|
5
|
-
|
6
|
-
|
7
|
-
class Automatic:
|
8
|
-
pass
|
9
|
-
|
10
|
-
|
11
|
-
class Syslog:
|
12
|
-
"""TODO deprecated; remove this special 'syslog' filename in the future"""
|
13
|
-
|
14
|
-
|
15
|
-
LOGFILE_NONES = ('none', 'off', None)
|
16
|
-
LOGFILE_AUTOS = (Automatic, 'auto')
|
17
|
-
LOGFILE_SYSLOGS = (Syslog, 'syslog')
|
18
|
-
|
19
|
-
|
20
|
-
def logfile_name(val):
|
21
|
-
if hasattr(val, 'lower'):
|
22
|
-
coerced = val.lower()
|
23
|
-
else:
|
24
|
-
coerced = val
|
25
|
-
|
26
|
-
if coerced in LOGFILE_NONES:
|
27
|
-
return None
|
28
|
-
elif coerced in LOGFILE_AUTOS:
|
29
|
-
return Automatic
|
30
|
-
elif coerced in LOGFILE_SYSLOGS:
|
31
|
-
return Syslog
|
32
|
-
else:
|
33
|
-
return existing_dirpath(val)
|
34
|
-
|
35
|
-
|
36
|
-
##
|
37
|
-
|
38
|
-
|
39
|
-
def octal_type(arg: ta.Union[str, int]) -> int:
|
40
|
-
if isinstance(arg, int):
|
41
|
-
return arg
|
42
|
-
try:
|
43
|
-
return int(arg, 8)
|
44
|
-
except (TypeError, ValueError):
|
45
|
-
raise ValueError(f'{arg} can not be converted to an octal type') # noqa
|
46
|
-
|
47
|
-
|
48
|
-
def existing_directory(v: str) -> str:
|
49
|
-
nv = os.path.expanduser(v)
|
50
|
-
if os.path.isdir(nv):
|
51
|
-
return nv
|
52
|
-
raise ValueError(f'{v} is not an existing directory')
|
53
|
-
|
54
|
-
|
55
|
-
def existing_dirpath(v: str) -> str:
|
56
|
-
nv = os.path.expanduser(v)
|
57
|
-
dir = os.path.dirname(nv) # noqa
|
58
|
-
if not dir:
|
59
|
-
# relative pathname with no directory component
|
60
|
-
return nv
|
61
|
-
if os.path.isdir(dir):
|
62
|
-
return nv
|
63
|
-
raise ValueError(f'The directory named as part of the path {v} does not exist')
|
64
|
-
|
65
|
-
|
66
|
-
def logging_level(value: ta.Union[str, int]) -> int:
|
67
|
-
if isinstance(value, int):
|
68
|
-
return value
|
69
|
-
s = str(value).lower()
|
70
|
-
level = logging.getLevelNamesMapping().get(s.upper())
|
71
|
-
if level is None:
|
72
|
-
raise ValueError(f'bad logging level name {value!r}')
|
73
|
-
return level
|
74
|
-
|
75
|
-
|
76
|
-
class SuffixMultiplier:
|
77
|
-
# d is a dictionary of suffixes to integer multipliers. If no suffixes match, default is the multiplier. Matches
|
78
|
-
# are case insensitive. Return values are in the fundamental unit.
|
79
|
-
def __init__(self, d, default=1):
|
80
|
-
super().__init__()
|
81
|
-
self._d = d
|
82
|
-
self._default = default
|
83
|
-
# all keys must be the same size
|
84
|
-
self._keysz = None
|
85
|
-
for k in d:
|
86
|
-
if self._keysz is None:
|
87
|
-
self._keysz = len(k)
|
88
|
-
elif self._keysz != len(k): # type: ignore
|
89
|
-
raise ValueError(k)
|
90
|
-
|
91
|
-
def __call__(self, v: ta.Union[str, int]) -> int:
|
92
|
-
if isinstance(v, int):
|
93
|
-
return v
|
94
|
-
v = v.lower()
|
95
|
-
for s, m in self._d.items():
|
96
|
-
if v[-self._keysz:] == s: # type: ignore
|
97
|
-
return int(v[:-self._keysz]) * m # type: ignore
|
98
|
-
return int(v) * self._default
|
99
|
-
|
100
|
-
|
101
|
-
byte_size = SuffixMultiplier({
|
102
|
-
'kb': 1024,
|
103
|
-
'mb': 1024 * 1024,
|
104
|
-
'gb': 1024 * 1024 * 1024,
|
105
|
-
})
|
106
|
-
|
107
|
-
|
108
|
-
class RestartWhenExitUnexpected:
|
109
|
-
pass
|
110
|
-
|
111
|
-
|
112
|
-
class RestartUnconditionally:
|
113
|
-
pass
|
ominfra/supervisor/utils.py
DELETED
@@ -1,206 +0,0 @@
|
|
1
|
-
# ruff: noqa: UP006 UP007
|
2
|
-
import errno
|
3
|
-
import os
|
4
|
-
import sys
|
5
|
-
import tempfile
|
6
|
-
import types
|
7
|
-
import typing as ta
|
8
|
-
|
9
|
-
from .signals import sig_name
|
10
|
-
|
11
|
-
|
12
|
-
T = ta.TypeVar('T')
|
13
|
-
|
14
|
-
|
15
|
-
##
|
16
|
-
|
17
|
-
|
18
|
-
def as_bytes(s: ta.Union[str, bytes], encoding: str = 'utf8') -> bytes:
|
19
|
-
if isinstance(s, bytes):
|
20
|
-
return s
|
21
|
-
else:
|
22
|
-
return s.encode(encoding)
|
23
|
-
|
24
|
-
|
25
|
-
def as_string(s: ta.Union[str, bytes], encoding: str = 'utf8') -> str:
|
26
|
-
if isinstance(s, str):
|
27
|
-
return s
|
28
|
-
else:
|
29
|
-
return s.decode(encoding)
|
30
|
-
|
31
|
-
|
32
|
-
def find_prefix_at_end(haystack: bytes, needle: bytes) -> int:
|
33
|
-
l = len(needle) - 1
|
34
|
-
while l and not haystack.endswith(needle[:l]):
|
35
|
-
l -= 1
|
36
|
-
return l
|
37
|
-
|
38
|
-
|
39
|
-
##
|
40
|
-
|
41
|
-
|
42
|
-
def compact_traceback() -> ta.Tuple[
|
43
|
-
ta.Tuple[str, str, int],
|
44
|
-
ta.Type[BaseException],
|
45
|
-
BaseException,
|
46
|
-
types.TracebackType,
|
47
|
-
]:
|
48
|
-
t, v, tb = sys.exc_info()
|
49
|
-
if not tb:
|
50
|
-
raise RuntimeError('No traceback')
|
51
|
-
|
52
|
-
tbinfo = []
|
53
|
-
while tb:
|
54
|
-
tbinfo.append((
|
55
|
-
tb.tb_frame.f_code.co_filename,
|
56
|
-
tb.tb_frame.f_code.co_name,
|
57
|
-
str(tb.tb_lineno),
|
58
|
-
))
|
59
|
-
tb = tb.tb_next
|
60
|
-
|
61
|
-
# just to be safe
|
62
|
-
del tb
|
63
|
-
|
64
|
-
file, function, line = tbinfo[-1]
|
65
|
-
info = ' '.join(['[%s|%s|%s]' % x for x in tbinfo]) # noqa
|
66
|
-
return (file, function, line), t, v, info # type: ignore
|
67
|
-
|
68
|
-
|
69
|
-
class ExitNow(Exception): # noqa
|
70
|
-
pass
|
71
|
-
|
72
|
-
|
73
|
-
def real_exit(code: int) -> None:
|
74
|
-
os._exit(code) # noqa
|
75
|
-
|
76
|
-
|
77
|
-
##
|
78
|
-
|
79
|
-
|
80
|
-
def decode_wait_status(sts: int) -> ta.Tuple[int, str]:
|
81
|
-
"""
|
82
|
-
Decode the status returned by wait() or waitpid().
|
83
|
-
|
84
|
-
Return a tuple (exitstatus, message) where exitstatus is the exit status, or -1 if the process was killed by a
|
85
|
-
signal; and message is a message telling what happened. It is the caller's responsibility to display the message.
|
86
|
-
"""
|
87
|
-
|
88
|
-
if os.WIFEXITED(sts):
|
89
|
-
es = os.WEXITSTATUS(sts) & 0xffff
|
90
|
-
msg = f'exit status {es}'
|
91
|
-
return es, msg
|
92
|
-
elif os.WIFSIGNALED(sts):
|
93
|
-
sig = os.WTERMSIG(sts)
|
94
|
-
msg = f'terminated by {sig_name(sig)}'
|
95
|
-
if hasattr(os, 'WCOREDUMP'):
|
96
|
-
iscore = os.WCOREDUMP(sts)
|
97
|
-
else:
|
98
|
-
iscore = bool(sts & 0x80)
|
99
|
-
if iscore:
|
100
|
-
msg += ' (core dumped)'
|
101
|
-
return -1, msg
|
102
|
-
else:
|
103
|
-
msg = 'unknown termination cause 0x%04x' % sts # noqa
|
104
|
-
return -1, msg
|
105
|
-
|
106
|
-
|
107
|
-
##
|
108
|
-
|
109
|
-
|
110
|
-
def read_fd(fd: int) -> bytes:
|
111
|
-
try:
|
112
|
-
data = os.read(fd, 2 << 16) # 128K
|
113
|
-
except OSError as why:
|
114
|
-
if why.args[0] not in (errno.EWOULDBLOCK, errno.EBADF, errno.EINTR):
|
115
|
-
raise
|
116
|
-
data = b''
|
117
|
-
return data
|
118
|
-
|
119
|
-
|
120
|
-
def try_unlink(path: str) -> bool:
|
121
|
-
try:
|
122
|
-
os.unlink(path)
|
123
|
-
except OSError:
|
124
|
-
return False
|
125
|
-
return True
|
126
|
-
|
127
|
-
|
128
|
-
def close_fd(fd: int) -> bool:
|
129
|
-
try:
|
130
|
-
os.close(fd)
|
131
|
-
except OSError:
|
132
|
-
return False
|
133
|
-
return True
|
134
|
-
|
135
|
-
|
136
|
-
def is_fd_open(fd: int) -> bool:
|
137
|
-
try:
|
138
|
-
n = os.dup(fd)
|
139
|
-
except OSError:
|
140
|
-
return False
|
141
|
-
os.close(n)
|
142
|
-
return True
|
143
|
-
|
144
|
-
|
145
|
-
def get_open_fds(limit: int) -> ta.FrozenSet[int]:
|
146
|
-
return frozenset(filter(is_fd_open, range(limit)))
|
147
|
-
|
148
|
-
|
149
|
-
def mktempfile(suffix: str, prefix: str, dir: str) -> str: # noqa
|
150
|
-
fd, filename = tempfile.mkstemp(suffix, prefix, dir)
|
151
|
-
os.close(fd)
|
152
|
-
return filename
|
153
|
-
|
154
|
-
|
155
|
-
##
|
156
|
-
|
157
|
-
|
158
|
-
def get_path() -> ta.Sequence[str]:
|
159
|
-
"""Return a list corresponding to $PATH, or a default."""
|
160
|
-
|
161
|
-
path = ['/bin', '/usr/bin', '/usr/local/bin']
|
162
|
-
if 'PATH' in os.environ:
|
163
|
-
p = os.environ['PATH']
|
164
|
-
if p:
|
165
|
-
path = p.split(os.pathsep)
|
166
|
-
return path
|
167
|
-
|
168
|
-
|
169
|
-
def normalize_path(v: str) -> str:
|
170
|
-
return os.path.normpath(os.path.abspath(os.path.expanduser(v)))
|
171
|
-
|
172
|
-
|
173
|
-
##
|
174
|
-
|
175
|
-
|
176
|
-
ANSI_ESCAPE_BEGIN = b'\x1b['
|
177
|
-
ANSI_TERMINATORS = (b'H', b'f', b'A', b'B', b'C', b'D', b'R', b's', b'u', b'J', b'K', b'h', b'l', b'p', b'm')
|
178
|
-
|
179
|
-
|
180
|
-
def strip_escapes(s: bytes) -> bytes:
|
181
|
-
"""Remove all ANSI color escapes from the given string."""
|
182
|
-
|
183
|
-
result = b''
|
184
|
-
show = 1
|
185
|
-
i = 0
|
186
|
-
l = len(s)
|
187
|
-
while i < l:
|
188
|
-
if show == 0 and s[i:i + 1] in ANSI_TERMINATORS:
|
189
|
-
show = 1
|
190
|
-
elif show:
|
191
|
-
n = s.find(ANSI_ESCAPE_BEGIN, i)
|
192
|
-
if n == -1:
|
193
|
-
return result + s[i:]
|
194
|
-
else:
|
195
|
-
result = result + s[i:n]
|
196
|
-
i = n
|
197
|
-
show = 0
|
198
|
-
i += 1
|
199
|
-
return result
|
200
|
-
|
201
|
-
|
202
|
-
##
|
203
|
-
|
204
|
-
|
205
|
-
def timeslice(period: int, when: float) -> int:
|
206
|
-
return int(when - (when % period))
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|