omdev 0.0.0.dev7__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.
- omdev/__about__.py +35 -0
- omdev/__init__.py +0 -0
- omdev/amalg/__init__.py +0 -0
- omdev/amalg/__main__.py +4 -0
- omdev/amalg/amalg.py +513 -0
- omdev/classdot.py +61 -0
- omdev/cmake.py +164 -0
- omdev/exts/__init__.py +0 -0
- omdev/exts/_distutils/__init__.py +10 -0
- omdev/exts/_distutils/build_ext.py +367 -0
- omdev/exts/_distutils/compilers/__init__.py +3 -0
- omdev/exts/_distutils/compilers/ccompiler.py +1032 -0
- omdev/exts/_distutils/compilers/options.py +80 -0
- omdev/exts/_distutils/compilers/unixccompiler.py +385 -0
- omdev/exts/_distutils/dir_util.py +76 -0
- omdev/exts/_distutils/errors.py +62 -0
- omdev/exts/_distutils/extension.py +107 -0
- omdev/exts/_distutils/file_util.py +216 -0
- omdev/exts/_distutils/modified.py +47 -0
- omdev/exts/_distutils/spawn.py +103 -0
- omdev/exts/_distutils/sysconfig.py +349 -0
- omdev/exts/_distutils/util.py +201 -0
- omdev/exts/_distutils/version.py +308 -0
- omdev/exts/build.py +43 -0
- omdev/exts/cmake.py +195 -0
- omdev/exts/importhook.py +88 -0
- omdev/exts/scan.py +74 -0
- omdev/interp/__init__.py +1 -0
- omdev/interp/__main__.py +4 -0
- omdev/interp/cli.py +63 -0
- omdev/interp/inspect.py +105 -0
- omdev/interp/providers.py +67 -0
- omdev/interp/pyenv.py +353 -0
- omdev/interp/resolvers.py +76 -0
- omdev/interp/standalone.py +187 -0
- omdev/interp/system.py +125 -0
- omdev/interp/types.py +92 -0
- omdev/mypy/__init__.py +0 -0
- omdev/mypy/debug.py +86 -0
- omdev/pyproject/__init__.py +1 -0
- omdev/pyproject/__main__.py +4 -0
- omdev/pyproject/cli.py +319 -0
- omdev/pyproject/configs.py +97 -0
- omdev/pyproject/ext.py +107 -0
- omdev/pyproject/pkg.py +196 -0
- omdev/scripts/__init__.py +0 -0
- omdev/scripts/execrss.py +19 -0
- omdev/scripts/findimports.py +62 -0
- omdev/scripts/findmagic.py +70 -0
- omdev/scripts/interp.py +2118 -0
- omdev/scripts/pyproject.py +3584 -0
- omdev/scripts/traceimport.py +502 -0
- omdev/tokens.py +42 -0
- omdev/toml/__init__.py +1 -0
- omdev/toml/parser.py +823 -0
- omdev/toml/writer.py +104 -0
- omdev/tools/__init__.py +0 -0
- omdev/tools/dockertools.py +81 -0
- omdev/tools/sqlrepl.py +193 -0
- omdev/versioning/__init__.py +1 -0
- omdev/versioning/specifiers.py +531 -0
- omdev/versioning/versions.py +416 -0
- omdev-0.0.0.dev7.dist-info/LICENSE +21 -0
- omdev-0.0.0.dev7.dist-info/METADATA +24 -0
- omdev-0.0.0.dev7.dist-info/RECORD +67 -0
- omdev-0.0.0.dev7.dist-info/WHEEL +5 -0
- omdev-0.0.0.dev7.dist-info/top_level.txt +1 -0
omdev/toml/writer.py
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import string
|
|
2
|
+
import typing as ta
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class TomlWriter:
|
|
6
|
+
def __init__(self, out: ta.TextIO) -> None:
|
|
7
|
+
super().__init__()
|
|
8
|
+
self._out = out
|
|
9
|
+
|
|
10
|
+
self._indent = 0
|
|
11
|
+
self._wrote_indent = False
|
|
12
|
+
|
|
13
|
+
#
|
|
14
|
+
|
|
15
|
+
def _w(self, s: str) -> None:
|
|
16
|
+
if not self._wrote_indent:
|
|
17
|
+
self._out.write(' ' * self._indent)
|
|
18
|
+
self._wrote_indent = True
|
|
19
|
+
self._out.write(s)
|
|
20
|
+
|
|
21
|
+
def _nl(self) -> None:
|
|
22
|
+
self._out.write('\n')
|
|
23
|
+
self._wrote_indent = False
|
|
24
|
+
|
|
25
|
+
def _needs_quote(self, s: str) -> bool:
|
|
26
|
+
return (
|
|
27
|
+
not s or
|
|
28
|
+
any(c in s for c in '\'"\n') or
|
|
29
|
+
s[0] not in string.ascii_letters
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
def _maybe_quote(self, s: str) -> str:
|
|
33
|
+
if self._needs_quote(s):
|
|
34
|
+
return repr(s)
|
|
35
|
+
else:
|
|
36
|
+
return s
|
|
37
|
+
|
|
38
|
+
#
|
|
39
|
+
|
|
40
|
+
def write_root(self, obj: ta.Mapping) -> None:
|
|
41
|
+
for i, (k, v) in enumerate(obj.items()):
|
|
42
|
+
if i:
|
|
43
|
+
self._nl()
|
|
44
|
+
self._w('[')
|
|
45
|
+
self._w(self._maybe_quote(k))
|
|
46
|
+
self._w(']')
|
|
47
|
+
self._nl()
|
|
48
|
+
self.write_table_contents(v)
|
|
49
|
+
|
|
50
|
+
def write_table_contents(self, obj: ta.Mapping) -> None:
|
|
51
|
+
for k, v in obj.items():
|
|
52
|
+
self.write_key(k)
|
|
53
|
+
self._w(' = ')
|
|
54
|
+
self.write_value(v)
|
|
55
|
+
self._nl()
|
|
56
|
+
|
|
57
|
+
def write_array(self, obj: ta.Sequence) -> None:
|
|
58
|
+
self._w('[')
|
|
59
|
+
self._nl()
|
|
60
|
+
self._indent += 1
|
|
61
|
+
for e in obj:
|
|
62
|
+
self.write_value(e)
|
|
63
|
+
self._w(',')
|
|
64
|
+
self._nl()
|
|
65
|
+
self._indent -= 1
|
|
66
|
+
self._w(']')
|
|
67
|
+
|
|
68
|
+
def write_inline_table(self, obj: ta.Mapping) -> None:
|
|
69
|
+
self._w('{')
|
|
70
|
+
for i, (k, v) in enumerate(obj.items()):
|
|
71
|
+
if i:
|
|
72
|
+
self._w(', ')
|
|
73
|
+
self.write_key(k)
|
|
74
|
+
self._w(' = ')
|
|
75
|
+
self.write_value(v)
|
|
76
|
+
self._w('}')
|
|
77
|
+
|
|
78
|
+
def write_inline_array(self, obj: ta.Sequence) -> None:
|
|
79
|
+
self._w('[')
|
|
80
|
+
for i, e in enumerate(obj):
|
|
81
|
+
if i:
|
|
82
|
+
self._w(', ')
|
|
83
|
+
self.write_value(e)
|
|
84
|
+
self._w(']')
|
|
85
|
+
|
|
86
|
+
def write_key(self, obj: ta.Any) -> None:
|
|
87
|
+
if isinstance(obj, str):
|
|
88
|
+
self._w(self._maybe_quote(obj.replace('_', '-')))
|
|
89
|
+
elif isinstance(obj, int):
|
|
90
|
+
self._w(repr(str(obj)))
|
|
91
|
+
else:
|
|
92
|
+
raise TypeError(obj)
|
|
93
|
+
|
|
94
|
+
def write_value(self, obj: ta.Any) -> None:
|
|
95
|
+
if isinstance(obj, bool):
|
|
96
|
+
self._w(str(obj).lower())
|
|
97
|
+
elif isinstance(obj, (str, int, float)):
|
|
98
|
+
self._w(repr(obj))
|
|
99
|
+
elif isinstance(obj, ta.Mapping):
|
|
100
|
+
self.write_inline_table(obj)
|
|
101
|
+
elif isinstance(obj, ta.Sequence):
|
|
102
|
+
self.write_array(obj)
|
|
103
|
+
else:
|
|
104
|
+
raise TypeError(obj)
|
omdev/tools/__init__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import shutil
|
|
3
|
+
import subprocess
|
|
4
|
+
|
|
5
|
+
from omlish import argparse as ap
|
|
6
|
+
from omlish import check
|
|
7
|
+
from omlish import lang
|
|
8
|
+
from omlish import logs
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@lang.cached_function
|
|
12
|
+
def docker_exe() -> str:
|
|
13
|
+
return check.not_none(shutil.which('docker'))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@lang.cached_function
|
|
17
|
+
def get_local_platform() -> str:
|
|
18
|
+
return subprocess.check_output([
|
|
19
|
+
docker_exe(),
|
|
20
|
+
'system',
|
|
21
|
+
'info',
|
|
22
|
+
'--format',
|
|
23
|
+
'{{.OSType}}/{{.Architecture}}',
|
|
24
|
+
]).decode().strip()
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class Cli(ap.Cli):
|
|
28
|
+
@ap.command(
|
|
29
|
+
ap.arg('args', nargs='*'),
|
|
30
|
+
)
|
|
31
|
+
def ns1(self) -> None:
|
|
32
|
+
"""
|
|
33
|
+
- https://gist.github.com/BretFisher/5e1a0c7bcca4c735e716abf62afad389
|
|
34
|
+
- https://github.com/justincormack/nsenter1/blob/8d3ba504b2c14d73c70cf34f1ec6943c093f1b02/nsenter1.c
|
|
35
|
+
|
|
36
|
+
alt:
|
|
37
|
+
- nc -U ~/Library/Containers/com.docker.docker/Data/debug-shell.sock
|
|
38
|
+
"""
|
|
39
|
+
os.execl(
|
|
40
|
+
exe := docker_exe(),
|
|
41
|
+
exe,
|
|
42
|
+
'run',
|
|
43
|
+
'--platform', get_local_platform(),
|
|
44
|
+
'--privileged',
|
|
45
|
+
'--pid=host',
|
|
46
|
+
'-it', 'debian',
|
|
47
|
+
'nsenter',
|
|
48
|
+
'-t', '1',
|
|
49
|
+
'-m', # mount
|
|
50
|
+
'-u', # uts
|
|
51
|
+
'-i', # ipc
|
|
52
|
+
'-n', # net
|
|
53
|
+
'-p', # pid
|
|
54
|
+
'-C', # cgroup
|
|
55
|
+
# '-U', # user
|
|
56
|
+
'-T', # time
|
|
57
|
+
*self.args.args,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
@ap.command(
|
|
61
|
+
ap.arg('--amd64', action='store_true'),
|
|
62
|
+
)
|
|
63
|
+
def enable_ptrace(self) -> None:
|
|
64
|
+
"""
|
|
65
|
+
- https://github.com/docker/for-mac/issues/5191
|
|
66
|
+
- https://forums.docker.com/t/sys-ptrace-capability-for-linux-amd64/138482/4
|
|
67
|
+
"""
|
|
68
|
+
os.execl(
|
|
69
|
+
exe := docker_exe(),
|
|
70
|
+
exe,
|
|
71
|
+
'run',
|
|
72
|
+
*(('--platform', 'linux/x86_64') if self.args.amd64 else ()),
|
|
73
|
+
'--privileged',
|
|
74
|
+
'-it', 'debian',
|
|
75
|
+
'sh', '-c', 'echo 0 > /proc/sys/kernel/yama/ptrace_scope',
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
if __name__ == '__main__':
|
|
80
|
+
logs.configure_standard_logging('INFO')
|
|
81
|
+
Cli()()
|
omdev/tools/sqlrepl.py
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import dataclasses as dc
|
|
2
|
+
import os.path
|
|
3
|
+
import shutil
|
|
4
|
+
import sys
|
|
5
|
+
import typing as ta
|
|
6
|
+
import urllib.parse
|
|
7
|
+
import warnings
|
|
8
|
+
|
|
9
|
+
import yaml
|
|
10
|
+
|
|
11
|
+
from omlish import argparse as ap
|
|
12
|
+
from omlish import check
|
|
13
|
+
from omlish import lang
|
|
14
|
+
from omlish import logs
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dc.dataclass(frozen=True)
|
|
18
|
+
class ServerSpec:
|
|
19
|
+
host: str
|
|
20
|
+
port: int | None = None
|
|
21
|
+
username: str | None = None
|
|
22
|
+
password: str | None = None
|
|
23
|
+
db: str | None = None
|
|
24
|
+
|
|
25
|
+
@classmethod
|
|
26
|
+
def from_url(cls, url: str) -> 'ServerSpec':
|
|
27
|
+
parsed = urllib.parse.urlparse(url)
|
|
28
|
+
if not parsed.hostname:
|
|
29
|
+
raise NameError(parsed.hostname)
|
|
30
|
+
if parsed.path:
|
|
31
|
+
if not parsed.path.startswith('/'):
|
|
32
|
+
raise NameError(parsed.path)
|
|
33
|
+
db = parsed.path[1:]
|
|
34
|
+
else:
|
|
35
|
+
db = None
|
|
36
|
+
return ServerSpec(
|
|
37
|
+
host=parsed.hostname,
|
|
38
|
+
port=parsed.port or None,
|
|
39
|
+
username=parsed.username or None,
|
|
40
|
+
password=parsed.password or None,
|
|
41
|
+
db=db,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def spec_from_mysql_docker_compose(svc: ta.Mapping[str, ta.Any]) -> ServerSpec:
|
|
46
|
+
env = svc['environment']
|
|
47
|
+
return ServerSpec(
|
|
48
|
+
host='localhost',
|
|
49
|
+
port=int(svc['ports'][0].split(':')[0]),
|
|
50
|
+
username=env.get('MYSQL_USER') or None,
|
|
51
|
+
password=env.get('MYSQL_PASSWORD') or None,
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def spec_from_postgres_docker_compose(svc: ta.Mapping[str, ta.Any]) -> ServerSpec:
|
|
56
|
+
env = svc['environment']
|
|
57
|
+
return ServerSpec(
|
|
58
|
+
host='localhost',
|
|
59
|
+
port=int(svc['ports'][0].split(':')[0]),
|
|
60
|
+
username=env.get('POSTGRES_USER') or None,
|
|
61
|
+
password=env.get('POSTGRES_PASSWORD') or None,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def spec_from_cfg(cfg: ta.Mapping[str, ta.Any], prefix: str) -> ServerSpec:
|
|
66
|
+
return ServerSpec(
|
|
67
|
+
host=cfg[prefix + '_host'],
|
|
68
|
+
port=cfg.get(prefix + '_port'),
|
|
69
|
+
username=cfg.get(prefix + '_user'),
|
|
70
|
+
password=cfg.get(prefix + '_pass'),
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@lang.cached_function
|
|
75
|
+
def _maybe_warn_pgcli_keyring() -> None:
|
|
76
|
+
import pgcli.config
|
|
77
|
+
|
|
78
|
+
c = pgcli.config.get_config()
|
|
79
|
+
if c['main'].as_bool('keyring'):
|
|
80
|
+
warnings.warn(
|
|
81
|
+
'pgcli keyring is not disabled, it will try to store credentials. '
|
|
82
|
+
'set `keyring = False` in ~/.config/pgcli/config',
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def _dbcli_or_fallback_exe(dbcli_mod: str | None, default_exe: str) -> tuple[ta.Sequence[str], bool]:
|
|
87
|
+
if dbcli_mod is not None:
|
|
88
|
+
main_mod = dbcli_mod + '.main'
|
|
89
|
+
try:
|
|
90
|
+
__import__(main_mod)
|
|
91
|
+
except ImportError:
|
|
92
|
+
pass
|
|
93
|
+
else:
|
|
94
|
+
if dbcli_mod == 'pgcli':
|
|
95
|
+
_maybe_warn_pgcli_keyring()
|
|
96
|
+
return [sys.executable, '-m', main_mod], True
|
|
97
|
+
return [check.not_none(shutil.which(default_exe))], False
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def exec_mysql_cli(
|
|
101
|
+
spec: ServerSpec,
|
|
102
|
+
*extra_args: str,
|
|
103
|
+
exe: ta.Iterable[str] | None = None,
|
|
104
|
+
no_dbcli: bool = False,
|
|
105
|
+
) -> ta.NoReturn:
|
|
106
|
+
if exe is not None:
|
|
107
|
+
args, is_dbcli = list(exe), False
|
|
108
|
+
else:
|
|
109
|
+
argsx, is_dbcli = _dbcli_or_fallback_exe(
|
|
110
|
+
'mycli' if not no_dbcli else None,
|
|
111
|
+
'mysql',
|
|
112
|
+
)
|
|
113
|
+
args = list(argsx)
|
|
114
|
+
if spec.username:
|
|
115
|
+
args.extend(['--user', spec.username])
|
|
116
|
+
if spec.password:
|
|
117
|
+
os.environ['MYSQL_PWD'] = spec.password
|
|
118
|
+
args.extend(['--host', spec.host])
|
|
119
|
+
if not is_dbcli:
|
|
120
|
+
args.append('--protocol=TCP')
|
|
121
|
+
if spec.port:
|
|
122
|
+
args.extend(['--port', str(spec.port)])
|
|
123
|
+
if spec.db:
|
|
124
|
+
args.append(spec.db)
|
|
125
|
+
args.extend(extra_args)
|
|
126
|
+
os.execvp(args[0], args)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def exec_postgres_cli(
|
|
130
|
+
spec: ServerSpec,
|
|
131
|
+
*extra_args: str,
|
|
132
|
+
exe: ta.Iterable[str] | None = None,
|
|
133
|
+
no_dbcli: bool = False,
|
|
134
|
+
) -> ta.NoReturn:
|
|
135
|
+
if exe is not None:
|
|
136
|
+
args, is_dbcli = list(exe), False
|
|
137
|
+
else:
|
|
138
|
+
argsx, is_dbcli = _dbcli_or_fallback_exe(
|
|
139
|
+
'pgcli' if not no_dbcli else None,
|
|
140
|
+
'psql',
|
|
141
|
+
)
|
|
142
|
+
args = list(argsx)
|
|
143
|
+
if spec.username:
|
|
144
|
+
args.extend(['--username', spec.username])
|
|
145
|
+
if spec.password:
|
|
146
|
+
os.environ['PGPASSWORD'] = spec.password
|
|
147
|
+
if spec.host:
|
|
148
|
+
args.extend(['--host', spec.host])
|
|
149
|
+
if spec.port:
|
|
150
|
+
args.extend(['--port', str(spec.port)])
|
|
151
|
+
if spec.db:
|
|
152
|
+
args.append(spec.db)
|
|
153
|
+
args.extend(extra_args)
|
|
154
|
+
os.execvp(args[0], args)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
class Cli(ap.Cli):
|
|
158
|
+
@ap.command(
|
|
159
|
+
ap.arg('--no-dbcli', action='store_true'),
|
|
160
|
+
ap.arg('dialect'),
|
|
161
|
+
ap.arg('target'),
|
|
162
|
+
ap.arg('args', nargs='*'),
|
|
163
|
+
)
|
|
164
|
+
def repl(self) -> None:
|
|
165
|
+
l, _, r = (target := self.args.target).partition(':')
|
|
166
|
+
_, lf = os.path.dirname(l), os.path.basename(l)
|
|
167
|
+
if not lf.endswith('.yml'):
|
|
168
|
+
raise Exception(f'unhandled target: {target=}')
|
|
169
|
+
with open(l) as f:
|
|
170
|
+
cfg = yaml.safe_load(f.read())
|
|
171
|
+
dialect = self.args.dialect
|
|
172
|
+
if lf == 'compose.yml':
|
|
173
|
+
svc = cfg['services'][r]
|
|
174
|
+
if dialect == 'mysql':
|
|
175
|
+
spec = spec_from_mysql_docker_compose(svc)
|
|
176
|
+
elif dialect == 'postgres':
|
|
177
|
+
spec = spec_from_postgres_docker_compose(svc)
|
|
178
|
+
else:
|
|
179
|
+
raise Exception(f'unhandled dialect: {dialect=}')
|
|
180
|
+
else:
|
|
181
|
+
spec = spec_from_cfg(cfg, r)
|
|
182
|
+
|
|
183
|
+
if dialect == 'mysql':
|
|
184
|
+
exec_mysql_cli(spec, *self.args.args, no_dbcli=self.args.no_dbcli)
|
|
185
|
+
elif dialect == 'postgres':
|
|
186
|
+
exec_postgres_cli(spec, *self.args.args, no_dbcli=self.args.no_dbcli)
|
|
187
|
+
else:
|
|
188
|
+
raise Exception(f'unhandled dialect: {dialect=}')
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
if __name__ == '__main__':
|
|
192
|
+
logs.configure_standard_logging('INFO')
|
|
193
|
+
Cli()()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# @omlish-lite
|