omdev 0.0.0.dev500__py3-none-any.whl → 0.0.0.dev506__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.

Potentially problematic release.


This version of omdev might be problematic. Click here for more details.

@@ -101,7 +101,7 @@ def __omlish_amalg__(): # noqa
101
101
  dict(path='../../omlish/lite/objects.py', sha1='9566bbf3530fd71fcc56321485216b592fae21e9'),
102
102
  dict(path='../../omlish/lite/reflect.py', sha1='c4fec44bf144e9d93293c996af06f6c65fc5e63d'),
103
103
  dict(path='../../omlish/lite/strings.py', sha1='89831ecbc34ad80e118a865eceb390ed399dc4d6'),
104
- dict(path='../../omlish/lite/typing.py', sha1='c501ff8f9ed08202e8016eaa098526d4deede834'),
104
+ dict(path='../../omlish/lite/typing.py', sha1='048bb5fb8ecad5be101516f8f3b7996707f5bc42'),
105
105
  dict(path='../../omlish/logs/levels.py', sha1='91405563d082a5eba874da82aac89d83ce7b6152'),
106
106
  dict(path='../../omlish/logs/std/filters.py', sha1='f36aab646d84d31e295b33aaaaa6f8b67ff38b3d'),
107
107
  dict(path='../../omlish/logs/std/proxy.py', sha1='3e7301a2aa351127f9c85f61b2f85dcc3f15aafb'),
@@ -109,9 +109,10 @@ def __omlish_amalg__(): # noqa
109
109
  dict(path='../cexts/magic.py', sha1='4e5ce6732454f75c9dd27352959708d8fa7b1666'),
110
110
  dict(path='../magic/find.py', sha1='436228a9cf1d8bab6b9234d09f72913b0960382f'),
111
111
  dict(path='../packaging/specifiers.py', sha1='a56ab4e8c9b174adb523921f6280ac41e0fce749'),
112
+ dict(path='versions.py', sha1='99aa1788f4eccb1901f21f2265862716d7580192'),
112
113
  dict(path='../../omlish/argparse/cli.py', sha1='f4dc3cd353d14386b5da0306768700e396afd2b3'),
113
114
  dict(path='../../omlish/lite/marshal.py', sha1='96348f5f2a26dc27d842d33cc3927e9da163436b'),
114
- dict(path='../../omlish/lite/maybes.py', sha1='bdf5136654ccd14b6a072588cad228925bdfbabd'),
115
+ dict(path='../../omlish/lite/maybes.py', sha1='04d2fcbea17028a5e6b8e7a7fb742375495ed233'),
115
116
  dict(path='../../omlish/lite/runtime.py', sha1='2e752a27ae2bf89b1bb79b4a2da522a3ec360c70'),
116
117
  dict(path='../../omlish/lite/timeouts.py', sha1='a0f673033a6943f242e35848d78a41892b9c62a1'),
117
118
  dict(path='../../omlish/logs/infos.py', sha1='4dd104bd468a8c438601dd0bbda619b47d2f1620'),
@@ -154,9 +155,9 @@ def __omlish_amalg__(): # noqa
154
155
  dict(path='../interp/inject.py', sha1='b039abbadf0b096d2724182af2e0ebda2a230852'),
155
156
  dict(path='../interp/default.py', sha1='a799969a0d3f4b57538587b13ceb08f6334ebc16'),
156
157
  dict(path='../interp/venvs.py', sha1='9ba8f2c3131d7d519d5cf36ca69b75f9c6fe2b27'),
157
- dict(path='configs.py', sha1='7b1c1ed034ecb728d67ff15e3bb2b21a218773c9'),
158
+ dict(path='configs.py', sha1='28d20c0288eef4a5c61dd9b95071b7b15958b575'),
158
159
  dict(path='venvs.py', sha1='9f1935171017aeb802da56e14d7f41d632a7aa25'),
159
- dict(path='cli.py', sha1='77efd5e792baa941a79adef6b363751dbd6a0d3e'),
160
+ dict(path='cli.py', sha1='ecf31ccef6b0e1d1505b46d24faf076b6be32760'),
160
161
  ],
161
162
  )
162
163
 
@@ -3292,6 +3293,21 @@ class CachedFunc0(ta.Generic[T]):
3292
3293
  return value
3293
3294
 
3294
3295
 
3296
+ @dc.dataclass(frozen=True)
3297
+ class AsyncCachedFunc0(ta.Generic[T]):
3298
+ fn: ta.Callable[[], ta.Awaitable[T]]
3299
+
3300
+ async def __call__(self) -> T:
3301
+ try:
3302
+ return object.__getattribute__(self, '_value')
3303
+ except AttributeError:
3304
+ pass
3305
+
3306
+ value = await self.fn()
3307
+ object.__setattr__(self, '_value', value)
3308
+ return value
3309
+
3310
+
3295
3311
  ##
3296
3312
 
3297
3313
 
@@ -4289,6 +4305,44 @@ class SpecifierSet(BaseSpecifier):
4289
4305
  return iter(filtered)
4290
4306
 
4291
4307
 
4308
+ ########################################
4309
+ # ../versions.py
4310
+
4311
+
4312
+ ##
4313
+
4314
+
4315
+ @dc.dataclass(frozen=True)
4316
+ class VersionsFile:
4317
+ name: ta.Optional[str] = '.versions'
4318
+
4319
+ @staticmethod
4320
+ def parse(s: str) -> ta.Mapping[str, str]:
4321
+ return {
4322
+ k: v
4323
+ for l in s.splitlines()
4324
+ if (sl := l.split('#')[0].strip())
4325
+ for k, _, v in (sl.partition('='),)
4326
+ }
4327
+
4328
+ @cached_nullary
4329
+ def contents(self) -> ta.Mapping[str, str]:
4330
+ if not self.name or not os.path.exists(self.name):
4331
+ return {}
4332
+ with open(self.name) as f:
4333
+ s = f.read()
4334
+ return self.parse(s)
4335
+
4336
+ @staticmethod
4337
+ def get_pythons(d: ta.Mapping[str, str]) -> ta.Mapping[str, str]:
4338
+ pfx = 'PYTHON_'
4339
+ return {k[len(pfx):].lower(): v for k, v in d.items() if k.startswith(pfx)}
4340
+
4341
+ @cached_nullary
4342
+ def pythons(self) -> ta.Mapping[str, str]:
4343
+ return self.get_pythons(self.contents())
4344
+
4345
+
4292
4346
  ########################################
4293
4347
  # ../../../omlish/argparse/cli.py
4294
4348
  """
@@ -5466,6 +5520,13 @@ class Maybe(ta.Generic[T]):
5466
5520
  else:
5467
5521
  return other
5468
5522
 
5523
+ @ta.final
5524
+ def or_none(self) -> ta.Optional[T]:
5525
+ if self.present:
5526
+ return self.must()
5527
+ else:
5528
+ return None
5529
+
5469
5530
  @ta.final
5470
5531
  def or_else_get(self, supplier: ta.Callable[[], ta.Union[T, U]]) -> ta.Union[T, U]:
5471
5532
  if self.present:
@@ -12355,7 +12416,7 @@ class PyprojectConfig:
12355
12416
  venvs: ta.Mapping[str, VenvConfig] = dc.field(default_factory=dict)
12356
12417
 
12357
12418
  venvs_dir: str = '.venvs'
12358
- versions_file: ta.Optional[str] = '.versions'
12419
+ # versions_file: ta.Optional[str] = '.versions' # FIXME:
12359
12420
 
12360
12421
 
12361
12422
  class PyprojectConfigPreparer:
@@ -12518,40 +12579,6 @@ class Venv:
12518
12579
  ##
12519
12580
 
12520
12581
 
12521
- @dc.dataclass(frozen=True)
12522
- class VersionsFile:
12523
- name: ta.Optional[str] = '.versions'
12524
-
12525
- @staticmethod
12526
- def parse(s: str) -> ta.Mapping[str, str]:
12527
- return {
12528
- k: v
12529
- for l in s.splitlines()
12530
- if (sl := l.split('#')[0].strip())
12531
- for k, _, v in (sl.partition('='),)
12532
- }
12533
-
12534
- @cached_nullary
12535
- def contents(self) -> ta.Mapping[str, str]:
12536
- if not self.name or not os.path.exists(self.name):
12537
- return {}
12538
- with open(self.name) as f:
12539
- s = f.read()
12540
- return self.parse(s)
12541
-
12542
- @staticmethod
12543
- def get_pythons(d: ta.Mapping[str, str]) -> ta.Mapping[str, str]:
12544
- pfx = 'PYTHON_'
12545
- return {k[len(pfx):].lower(): v for k, v in d.items() if k.startswith(pfx)}
12546
-
12547
- @cached_nullary
12548
- def pythons(self) -> ta.Mapping[str, str]:
12549
- return self.get_pythons(self.contents())
12550
-
12551
-
12552
- ##
12553
-
12554
-
12555
12582
  @cached_nullary
12556
12583
  def _script_rel_path() -> str:
12557
12584
  cwd = os.getcwd()
omdev/tools/sqlrepl.py CHANGED
@@ -1,3 +1,10 @@
1
+ """
2
+ TODO:
3
+ - sqlite
4
+ - unify-ish with omlish.sql
5
+ """
6
+ import abc
7
+ import configparser
1
8
  import dataclasses as dc
2
9
  import os.path
3
10
  import shutil
@@ -76,104 +83,197 @@ def spec_from_cfg(cfg: ta.Mapping[str, ta.Any], prefix: str) -> ServerSpec:
76
83
  )
77
84
 
78
85
 
79
- @lang.cached_function
80
- def _maybe_warn_pgcli_keyring() -> None:
81
- import pgcli.config
86
+ ##
87
+
88
+
89
+ @dc.dataclass(frozen=True)
90
+ class ReplArgs:
91
+ spec: ServerSpec
92
+ extra_args: ta.Sequence[str] | None = None # noqa
93
+
94
+ _: dc.KW_ONLY
95
+
96
+ exe: ta.Sequence[str] | None = None
97
+
98
+ no_dbcli: bool = False
99
+ no_import: bool = False
100
+ no_uv: bool = False
101
+ dbcli_version: str | None = None
102
+
103
+
104
+ class ReplRunner(lang.Abstract):
105
+ def __init__(self, args: ReplArgs) -> None:
106
+ super().__init__()
107
+
108
+ self._args = args
109
+
110
+ exe_name: ta.ClassVar[str]
111
+ dbcli_name: ta.ClassVar[str | None] = None
112
+
113
+ #
114
+
115
+ class Exe(ta.NamedTuple):
116
+ args: ta.Sequence[str]
117
+ is_dbcli: bool
118
+
119
+ @lang.cached_function
120
+ def exe(self) -> Exe:
121
+ if self._args.exe is not None:
122
+ if isinstance(self._args.exe, str):
123
+ return ReplRunner.Exe([self._args.exe], False)
124
+ else:
125
+ return ReplRunner.Exe(list(self._args.exe), False)
126
+
127
+ def default():
128
+ return ReplRunner.Exe([check.not_none(shutil.which(self.exe_name))], False)
129
+
130
+ if self._args.no_dbcli or self.dbcli_name is None:
131
+ return default()
132
+
133
+ if not self._args.no_import:
134
+ main_mod = self.dbcli_name + '.main'
135
+
136
+ try:
137
+ __import__(main_mod)
138
+ except ImportError:
139
+ pass
140
+ else:
141
+ return ReplRunner.Exe([sys.executable, '-m', main_mod], True)
142
+
143
+ if not self._args.no_uv and (uv_exe := shutil.which('uv')) is not None:
144
+ uv_arg = self.dbcli_name
145
+ if self._args.dbcli_version is not None:
146
+ uv_arg += f'@{self._args.dbcli_version}'
147
+
148
+ return ReplRunner.Exe([uv_exe, 'tool', 'run', uv_arg], True)
149
+
150
+ return default()
151
+
152
+ #
153
+
154
+ @abc.abstractmethod
155
+ def build_args(self) -> ta.Sequence[str]:
156
+ raise NotImplementedError
157
+
158
+ def pre_exec(self) -> None:
159
+ pass
160
+
161
+ #
162
+
163
+ def run(self) -> ta.NoReturn:
164
+ lst: list[str] = [
165
+ *self.exe().args,
166
+ *self.build_args(),
167
+ ]
168
+
169
+ self.pre_exec()
170
+
171
+ os.execvp(lst[0], lst)
172
+
173
+
174
+ class MysqlReplRunner(ReplRunner):
175
+ dbcli_name = 'mycli'
176
+ exe_name = 'mysql'
177
+
178
+ def build_args(self) -> ta.Sequence[str]:
179
+ lst: list[str] = []
180
+
181
+ if self._args.spec.username:
182
+ lst.extend(['--user', self._args.spec.username])
183
+
184
+ lst.extend(['--host', self._args.spec.host])
185
+ if not self.exe().is_dbcli:
186
+ lst.append('--protocol=TCP')
187
+ if self._args.spec.port:
188
+ lst.extend(['--port', str(self._args.spec.port)])
189
+
190
+ if self._args.spec.db:
191
+ lst.append(self._args.spec.db)
192
+
193
+ lst.extend(self._args.extra_args or [])
194
+
195
+ return lst
196
+
197
+ def pre_exec(self) -> None:
198
+ super().pre_exec()
199
+
200
+ if self._args.spec.password:
201
+ os.environ['MYSQL_PWD'] = self._args.spec.password
202
+
203
+
204
+ class PostgresReplRunner(ReplRunner):
205
+ dbcli_name = 'pgcli'
206
+ exe_name = 'psql'
207
+
208
+ def build_args(self) -> ta.Sequence[str]:
209
+ lst: list[str] = []
210
+
211
+ if self._args.spec.username:
212
+ lst.extend(['--username', self._args.spec.username])
213
+
214
+ if self._args.spec.host:
215
+ lst.extend(['--host', self._args.spec.host])
216
+ if self._args.spec.port:
217
+ lst.extend(['--port', str(self._args.spec.port)])
218
+
219
+ if self._args.spec.db:
220
+ lst.append(self._args.spec.db)
221
+
222
+ lst.extend(self._args.extra_args or [])
223
+
224
+ return lst
225
+
226
+ def _maybe_warn_keyring(self) -> None:
227
+ if 'XDG_CONFIG_HOME' in os.environ:
228
+ cfg_dir = f'{os.path.expanduser(os.environ["XDG_CONFIG_HOME"])}/pgcli/'
229
+ else:
230
+ cfg_dir = os.path.expanduser('~/.config/pgcli/')
231
+ cfg_path = os.path.join(cfg_dir, 'config')
232
+
233
+ if os.path.exists(cfg_path):
234
+ cfg = configparser.ConfigParser()
235
+ cfg.read(cfg_path)
236
+
237
+ if cfg.has_section('main') and not cfg.getboolean('main', 'keyring', fallback=True):
238
+ return
82
239
 
83
- c = pgcli.config.get_config()
84
- if c['main'].as_bool('keyring'):
85
240
  warnings.warn(
86
241
  'pgcli keyring is not disabled, it will try to store credentials. '
87
- 'set `keyring = False` in ~/.config/pgcli/config',
242
+ 'set `[main] keyring = False` in ~/.config/pgcli/config',
88
243
  )
89
244
 
245
+ def pre_exec(self) -> None:
246
+ super().pre_exec()
90
247
 
91
- def _dbcli_or_fallback_exe(dbcli_mod: str | None, default_exe: str) -> tuple[ta.Sequence[str], bool]:
92
- if dbcli_mod is not None:
93
- main_mod = dbcli_mod + '.main'
94
- try:
95
- __import__(main_mod)
96
- except ImportError:
97
- pass
98
- else:
99
- if dbcli_mod == 'pgcli':
100
- _maybe_warn_pgcli_keyring()
101
- return [sys.executable, '-m', main_mod], True
102
- return [check.not_none(shutil.which(default_exe))], False
103
-
104
-
105
- def exec_mysql_cli(
106
- spec: ServerSpec,
107
- *extra_args: str,
108
- exe: ta.Iterable[str] | None = None,
109
- no_dbcli: bool = False,
110
- ) -> ta.NoReturn:
111
- if exe is not None:
112
- args, is_dbcli = list(exe), False
113
- else:
114
- argsx, is_dbcli = _dbcli_or_fallback_exe(
115
- 'mycli' if not no_dbcli else None,
116
- 'mysql',
117
- )
118
- args = list(argsx)
119
- if spec.username:
120
- args.extend(['--user', spec.username])
121
- if spec.password:
122
- os.environ['MYSQL_PWD'] = spec.password
123
- args.extend(['--host', spec.host])
124
- if not is_dbcli:
125
- args.append('--protocol=TCP')
126
- if spec.port:
127
- args.extend(['--port', str(spec.port)])
128
- if spec.db:
129
- args.append(spec.db)
130
- args.extend(extra_args)
131
- os.execvp(args[0], args)
132
-
133
-
134
- def exec_postgres_cli(
135
- spec: ServerSpec,
136
- *extra_args: str,
137
- exe: ta.Iterable[str] | None = None,
138
- no_dbcli: bool = False,
139
- ) -> ta.NoReturn:
140
- if exe is not None:
141
- args, is_dbcli = list(exe), False
142
- else:
143
- argsx, is_dbcli = _dbcli_or_fallback_exe(
144
- 'pgcli' if not no_dbcli else None,
145
- 'psql',
146
- )
147
- args = list(argsx)
148
- if spec.username:
149
- args.extend(['--username', spec.username])
150
- if spec.password:
151
- os.environ['PGPASSWORD'] = spec.password
152
- if spec.host:
153
- args.extend(['--host', spec.host])
154
- if spec.port:
155
- args.extend(['--port', str(spec.port)])
156
- if spec.db:
157
- args.append(spec.db)
158
- args.extend(extra_args)
159
- os.execvp(args[0], args)
248
+ self._maybe_warn_keyring()
249
+
250
+ if self._args.spec.password:
251
+ os.environ['PGPASSWORD'] = self._args.spec.password
252
+
253
+
254
+ ##
160
255
 
161
256
 
162
257
  class Cli(ap.Cli):
163
258
  @ap.cmd(
164
- ap.arg('--no-dbcli', action='store_true'),
165
259
  ap.arg('dialect'),
166
260
  ap.arg('target'),
167
261
  ap.arg('args', nargs='*'),
262
+ ap.arg('--no-dbcli', action='store_true'),
263
+ ap.arg('--no-import', action='store_true'),
264
+ ap.arg('--no-uv', action='store_true'),
168
265
  )
169
266
  def repl(self) -> None:
170
267
  l, _, r = (target := self.args.target).partition(':')
171
268
  _, lf = os.path.dirname(l), os.path.basename(l)
172
269
  if not lf.endswith('.yml'):
173
270
  raise Exception(f'unhandled target: {target=}')
271
+
174
272
  with open(l) as f:
175
273
  cfg = yaml.safe_load(f.read())
274
+
176
275
  dialect = self.args.dialect
276
+
177
277
  if lf == 'compose.yml':
178
278
  svc = cfg['services'][r]
179
279
  if dialect == 'mysql':
@@ -185,13 +285,24 @@ class Cli(ap.Cli):
185
285
  else:
186
286
  spec = spec_from_cfg(cfg, r)
187
287
 
288
+ repl_args = ReplArgs(
289
+ spec,
290
+ self.args.args,
291
+ no_dbcli=self.args.no_dbcli,
292
+ no_import=self.args.no_import,
293
+ no_uv=self.args.no_uv,
294
+ )
295
+
296
+ repl_run: ReplRunner
188
297
  if dialect == 'mysql':
189
- exec_mysql_cli(spec, *self.args.args, no_dbcli=self.args.no_dbcli)
298
+ repl_run = MysqlReplRunner(repl_args)
190
299
  elif dialect == 'postgres':
191
- exec_postgres_cli(spec, *self.args.args, no_dbcli=self.args.no_dbcli)
300
+ repl_run = PostgresReplRunner(repl_args)
192
301
  else:
193
302
  raise Exception(f'unhandled dialect: {dialect=}')
194
303
 
304
+ repl_run.run()
305
+
195
306
 
196
307
  # @omlish-manifest
197
308
  _CLI_MODULE = CliModule('sqlrepl', __name__)