omdev 0.0.0.dev179__py3-none-any.whl → 0.0.0.dev181__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/.manifests.json CHANGED
@@ -96,14 +96,14 @@
96
96
  }
97
97
  },
98
98
  {
99
- "module": ".magic.find",
99
+ "module": ".magic.__main__",
100
100
  "attr": "_CLI_MODULE",
101
- "file": "omdev/magic/find.py",
102
- "line": 230,
101
+ "file": "omdev/magic/__main__.py",
102
+ "line": 4,
103
103
  "value": {
104
104
  "$.cli.types.CliModule": {
105
- "cmd_name": "py/findmagic",
106
- "mod_name": "omdev.magic.find"
105
+ "cmd_name": "magic",
106
+ "mod_name": "omdev.magic.__main__"
107
107
  }
108
108
  }
109
109
  },
omdev/cli/clicli.py CHANGED
@@ -21,15 +21,15 @@ class CliCli(ap.Cli):
21
21
 
22
22
  #
23
23
 
24
- @ap.command(name='version', aliases=['ver'])
24
+ @ap.cmd(name='version', aliases=['ver'])
25
25
  def print_version(self) -> None:
26
26
  print(__about__.__version__)
27
27
 
28
- @ap.command(name='revision', aliases=['rev'])
28
+ @ap.cmd(name='revision', aliases=['rev'])
29
29
  def print_revision(self) -> None:
30
30
  print(__about__.__revision__)
31
31
 
32
- @ap.command(name='home')
32
+ @ap.cmd(name='home')
33
33
  def print_home(self) -> None:
34
34
  print(sys.prefix)
35
35
 
@@ -52,7 +52,7 @@ class CliCli(ap.Cli):
52
52
  ],
53
53
  )
54
54
 
55
- @ap.command(
55
+ @ap.cmd(
56
56
  ap.arg('args', nargs=ap.REMAINDER),
57
57
  name='python',
58
58
  accepts_unknown=True,
@@ -60,7 +60,7 @@ class CliCli(ap.Cli):
60
60
  def python_cmd(self) -> None:
61
61
  self._passthrough_args_cmd(sys.executable)
62
62
 
63
- @ap.command(
63
+ @ap.cmd(
64
64
  ap.arg('args', nargs=ap.REMAINDER),
65
65
  name='pip',
66
66
  accepts_unknown=True,
@@ -70,7 +70,7 @@ class CliCli(ap.Cli):
70
70
 
71
71
  #
72
72
 
73
- @ap.command(
73
+ @ap.cmd(
74
74
  ap.arg('--url', default=DEFAULT_REINSTALL_URL),
75
75
  ap.arg('--local', action='store_true'),
76
76
  ap.arg('extra_deps', nargs='*'),
omdev/imgur.py CHANGED
@@ -107,7 +107,7 @@ def _main() -> None:
107
107
  from omlish.argparse import all as ap
108
108
 
109
109
  class Cli(ap.Cli):
110
- @ap.command(
110
+ @ap.cmd(
111
111
  ap.arg('file'),
112
112
  )
113
113
  def upload(self) -> None:
omdev/interp/cli.py CHANGED
@@ -12,7 +12,7 @@ import typing as ta
12
12
 
13
13
  from omlish.argparse.cli import ArgparseCli
14
14
  from omlish.argparse.cli import argparse_arg
15
- from omlish.argparse.cli import argparse_command
15
+ from omlish.argparse.cli import argparse_cmd
16
16
  from omlish.lite.cached import cached_nullary
17
17
  from omlish.lite.check import check
18
18
  from omlish.lite.inject import Injector
@@ -37,7 +37,7 @@ class InterpCli(ArgparseCli):
37
37
 
38
38
  #
39
39
 
40
- @argparse_command(
40
+ @argparse_cmd(
41
41
  argparse_arg('version'),
42
42
  argparse_arg('-d', '--debug', action='store_true'),
43
43
  )
@@ -46,7 +46,7 @@ class InterpCli(ArgparseCli):
46
46
  s = InterpSpecifier.parse(self.args.version)
47
47
  await r.list(s)
48
48
 
49
- @argparse_command(
49
+ @argparse_cmd(
50
50
  argparse_arg('version'),
51
51
  argparse_arg('-p', '--provider'),
52
52
  argparse_arg('-d', '--debug', action='store_true'),
omdev/interp/inspect.py CHANGED
@@ -6,7 +6,6 @@ import sys
6
6
  import typing as ta
7
7
 
8
8
  from omlish.asyncs.asyncio.subprocesses import asyncio_subprocesses
9
- from omlish.lite.logs import log
10
9
 
11
10
  from ..packaging.versions import Version
12
11
  from .types import InterpOpts
@@ -43,9 +42,15 @@ class InterpInspection:
43
42
 
44
43
 
45
44
  class InterpInspector:
46
- def __init__(self) -> None:
45
+ def __init__(
46
+ self,
47
+ *,
48
+ log: ta.Optional[logging.Logger] = None,
49
+ ) -> None:
47
50
  super().__init__()
48
51
 
52
+ self._log = log
53
+
49
54
  self._cache: ta.Dict[str, ta.Optional[InterpInspection]] = {}
50
55
 
51
56
  _RAW_INSPECTION_CODE = """
@@ -94,8 +99,8 @@ class InterpInspector:
94
99
  try:
95
100
  ret = await self._inspect(exe)
96
101
  except Exception as e: # noqa
97
- if log.isEnabledFor(logging.DEBUG):
98
- log.exception('Failed to inspect interp: %s', exe)
102
+ if self._log is not None and self._log.isEnabledFor(logging.DEBUG):
103
+ self._log.exception('Failed to inspect interp: %s', exe)
99
104
  ret = None
100
105
  self._cache[exe] = ret
101
106
  return ret
@@ -5,13 +5,13 @@ TODO:
5
5
  - check if path py's are venvs: sys.prefix != sys.base_prefix
6
6
  """
7
7
  import dataclasses as dc
8
+ import logging
8
9
  import os
9
10
  import re
10
11
  import typing as ta
11
12
 
12
13
  from omlish.lite.cached import cached_nullary
13
14
  from omlish.lite.check import check
14
- from omlish.lite.logs import log
15
15
 
16
16
  from ...packaging.versions import InvalidVersion
17
17
  from ..inspect import InterpInspector
@@ -37,12 +37,14 @@ class SystemInterpProvider(InterpProvider):
37
37
  options: Options = Options(),
38
38
  *,
39
39
  inspector: ta.Optional[InterpInspector] = None,
40
+ log: ta.Optional[logging.Logger] = None,
40
41
  ) -> None:
41
42
  super().__init__()
42
43
 
43
44
  self._options = options
44
45
 
45
46
  self._inspector = inspector
47
+ self._log = log
46
48
 
47
49
  #
48
50
 
@@ -116,7 +118,8 @@ class SystemInterpProvider(InterpProvider):
116
118
  lst = []
117
119
  for e in self.exes():
118
120
  if (ev := await self.get_exe_version(e)) is None:
119
- log.debug('Invalid system version: %s', e)
121
+ if self._log is not None:
122
+ self._log.debug('Invalid system version: %s', e)
120
123
  continue
121
124
  lst.append((e, ev))
122
125
  return lst
@@ -13,6 +13,7 @@ TODO:
13
13
  import abc
14
14
  import dataclasses as dc
15
15
  import itertools
16
+ import logging
16
17
  import os.path
17
18
  import shutil
18
19
  import sys
@@ -22,7 +23,6 @@ from omlish.asyncs.asyncio.subprocesses import asyncio_subprocesses
22
23
  from omlish.lite.cached import async_cached_nullary
23
24
  from omlish.lite.cached import cached_nullary
24
25
  from omlish.lite.check import check
25
- from omlish.lite.logs import log
26
26
 
27
27
  from ...packaging.versions import InvalidVersion
28
28
  from ...packaging.versions import Version
@@ -355,6 +355,7 @@ class PyenvInterpProvider(InterpProvider):
355
355
  *,
356
356
  pyenv: Pyenv,
357
357
  inspector: InterpInspector,
358
+ log: ta.Optional[logging.Logger] = None,
358
359
  ) -> None:
359
360
  super().__init__()
360
361
 
@@ -362,6 +363,7 @@ class PyenvInterpProvider(InterpProvider):
362
363
 
363
364
  self._pyenv = pyenv
364
365
  self._inspector = inspector
366
+ self._log = log
365
367
 
366
368
  #
367
369
 
@@ -406,7 +408,8 @@ class PyenvInterpProvider(InterpProvider):
406
408
  ret: ta.List[PyenvInterpProvider.Installed] = []
407
409
  for vn, ep in await self._pyenv.version_exes():
408
410
  if (i := await self._make_installed(vn, ep)) is None:
409
- log.debug('Invalid pyenv version: %s', vn)
411
+ if self._log is not None:
412
+ self._log.debug('Invalid pyenv version: %s', vn)
410
413
  continue
411
414
  ret.append(i)
412
415
  return ret
omdev/interp/venvs.py ADDED
@@ -0,0 +1,114 @@
1
+ # ruff: noqa: UP006 UP007
2
+ import dataclasses as dc
3
+ import logging
4
+ import os.path
5
+ import typing as ta
6
+
7
+ from omlish.asyncs.asyncio.subprocesses import asyncio_subprocesses
8
+ from omlish.lite.cached import async_cached_nullary
9
+ from omlish.lite.cached import cached_nullary
10
+ from omlish.lite.check import check
11
+ from omlish.lite.typing import Func2
12
+
13
+ from .default import get_default_interp_resolver
14
+ from .types import InterpSpecifier
15
+
16
+
17
+ ##
18
+
19
+
20
+ @dc.dataclass(frozen=True)
21
+ class InterpVenvConfig:
22
+ interp: ta.Optional[str] = None
23
+ requires: ta.Optional[ta.Sequence[str]] = None
24
+ use_uv: ta.Optional[bool] = None
25
+
26
+
27
+ class InterpVenvRequirementsProcessor(Func2['InterpVenv', ta.Sequence[str], ta.Sequence[str]]):
28
+ pass
29
+
30
+
31
+ class InterpVenv:
32
+ def __init__(
33
+ self,
34
+ path: str,
35
+ cfg: InterpVenvConfig,
36
+ *,
37
+ requirements_processor: ta.Optional[InterpVenvRequirementsProcessor] = None,
38
+ log: ta.Optional[logging.Logger] = None,
39
+ ) -> None:
40
+ super().__init__()
41
+
42
+ self._path = path
43
+ self._cfg = cfg
44
+
45
+ self._requirements_processor = requirements_processor
46
+ self._log = log
47
+
48
+ @property
49
+ def path(self) -> str:
50
+ return self._path
51
+
52
+ @property
53
+ def cfg(self) -> InterpVenvConfig:
54
+ return self._cfg
55
+
56
+ @async_cached_nullary
57
+ async def interp_exe(self) -> str:
58
+ i = InterpSpecifier.parse(check.not_none(self._cfg.interp))
59
+ return check.not_none(await get_default_interp_resolver().resolve(i, install=True)).exe
60
+
61
+ @cached_nullary
62
+ def exe(self) -> str:
63
+ ve = os.path.join(self._path, 'bin/python')
64
+ if not os.path.isfile(ve):
65
+ raise Exception(f'venv exe {ve} does not exist or is not a file!')
66
+ return ve
67
+
68
+ @async_cached_nullary
69
+ async def create(self) -> bool:
70
+ if os.path.exists(dn := self._path):
71
+ if not os.path.isdir(dn):
72
+ raise Exception(f'{dn} exists but is not a directory!')
73
+ return False
74
+
75
+ ie = await self.interp_exe()
76
+
77
+ if self._log is not None:
78
+ self._log.info('Using interpreter %s', ie)
79
+
80
+ await asyncio_subprocesses.check_call(ie, '-m', 'venv', dn)
81
+
82
+ ve = self.exe()
83
+ uv = self._cfg.use_uv
84
+
85
+ await asyncio_subprocesses.check_call(
86
+ ve,
87
+ '-m', 'pip',
88
+ 'install', '-v', '--upgrade',
89
+ 'pip',
90
+ 'setuptools',
91
+ 'wheel',
92
+ *(['uv'] if uv else []),
93
+ )
94
+
95
+ if sr := self._cfg.requires:
96
+ reqs = list(sr)
97
+ if self._requirements_processor is not None:
98
+ reqs = list(self._requirements_processor(self, reqs))
99
+
100
+ # TODO: automatically try slower uv download when it fails? lol
101
+ # Caused by: Failed to download distribution due to network timeout. Try increasing UV_HTTP_TIMEOUT (current value: 30s). # noqa
102
+ # UV_CONCURRENT_DOWNLOADS=4 UV_HTTP_TIMEOUT=3600
103
+
104
+ await asyncio_subprocesses.check_call(
105
+ ve,
106
+ '-m',
107
+ *(['uv'] if uv else []),
108
+ 'pip',
109
+ 'install',
110
+ *([] if uv else ['-v']),
111
+ *reqs,
112
+ )
113
+
114
+ return True
@@ -0,0 +1,11 @@
1
+ from ..cli import CliModule
2
+
3
+
4
+ # @omlish-manifest
5
+ _CLI_MODULE = CliModule('magic', __name__)
6
+
7
+
8
+ if __name__ == '__main__':
9
+ from .cli import _main
10
+
11
+ _main()
omdev/magic/cli.py ADDED
@@ -0,0 +1,54 @@
1
+ # ruff: noqa: UP006 UP007
2
+ import typing as ta
3
+
4
+ from omlish.argparse.cli import ArgparseCli
5
+ from omlish.argparse.cli import argparse_arg
6
+ from omlish.argparse.cli import argparse_cmd
7
+
8
+ from .find import find_magic_files
9
+ from .find import find_magic_py_modules
10
+ from .styles import C_MAGIC_STYLE
11
+ from .styles import PY_MAGIC_STYLE
12
+
13
+
14
+ ##
15
+
16
+
17
+ class MagicCli(ArgparseCli):
18
+ @argparse_cmd(
19
+ argparse_arg('--style', '-s', default='py'),
20
+ argparse_arg('--key', '-k', dest='keys', action='append'),
21
+ argparse_arg('--modules', action='store_true'),
22
+ argparse_arg('roots', nargs='*'),
23
+ )
24
+ def find(self) -> None:
25
+ style = {
26
+ 'py': PY_MAGIC_STYLE,
27
+ 'c': C_MAGIC_STYLE,
28
+ }[self.args.style]
29
+
30
+ kw: dict = dict(
31
+ roots=self.args.roots,
32
+ style=style,
33
+ keys=self.args.keys,
34
+ )
35
+
36
+ fn: ta.Callable
37
+ if self.args.modules:
38
+ fn = find_magic_py_modules
39
+ else:
40
+ fn = find_magic_files
41
+
42
+ for out in fn(**kw):
43
+ print(out)
44
+
45
+
46
+ ##
47
+
48
+
49
+ def _main(argv=None) -> None:
50
+ MagicCli(argv).cli_run_and_exit()
51
+
52
+
53
+ if __name__ == '__main__':
54
+ _main()
omdev/magic/find.py CHANGED
@@ -7,7 +7,6 @@ import typing as ta
7
7
  from .magic import Magic
8
8
  from .prepare import MagicPrepareError
9
9
  from .prepare import py_compile_magic_preparer
10
- from .styles import C_MAGIC_STYLE
11
10
  from .styles import PY_MAGIC_STYLE
12
11
  from .styles import MagicStyle
13
12
 
@@ -222,47 +221,3 @@ def find_magic_py_modules(
222
221
  yield fp[:-3].replace(os.sep, '.')
223
222
  else:
224
223
  yield fp
225
-
226
-
227
- ##
228
-
229
-
230
- # @omlish-manifest
231
- _CLI_MODULE = {'$omdev.cli.types.CliModule': {
232
- 'cmd_name': 'py/findmagic',
233
- 'mod_name': __name__,
234
- }}
235
-
236
-
237
- if __name__ == '__main__':
238
- def _main(argv=None) -> None:
239
- import argparse
240
-
241
- arg_parser = argparse.ArgumentParser()
242
- arg_parser.add_argument('--style', '-s', default='py')
243
- arg_parser.add_argument('--key', '-k', dest='keys', action='append')
244
- arg_parser.add_argument('--modules', action='store_true')
245
- arg_parser.add_argument('roots', nargs='*')
246
- args = arg_parser.parse_args(argv)
247
-
248
- style = {
249
- 'py': PY_MAGIC_STYLE,
250
- 'c': C_MAGIC_STYLE,
251
- }[args.style]
252
-
253
- kw: dict = dict(
254
- roots=args.roots,
255
- style=style,
256
- keys=args.keys,
257
- )
258
-
259
- fn: ta.Callable
260
- if args.modules:
261
- fn = find_magic_py_modules
262
- else:
263
- fn = find_magic_files
264
-
265
- for out in fn(**kw):
266
- print(out)
267
-
268
- _main()
omdev/pycharm/cli.py CHANGED
@@ -77,11 +77,11 @@ def parse_wmctrl_lxp_line(l: str) -> WmctrlLine:
77
77
 
78
78
 
79
79
  class Cli(ap.Cli):
80
- @ap.command()
80
+ @ap.cmd()
81
81
  def version(self) -> None:
82
82
  print(get_pycharm_version())
83
83
 
84
- @ap.command(
84
+ @ap.cmd(
85
85
  ap.arg('python-exe'),
86
86
  ap.arg('args', nargs=ap.REMAINDER),
87
87
  )
@@ -99,7 +99,7 @@ class Cli(ap.Cli):
99
99
  proc = subprocess.run([exe, src_file, *self.args.args], check=False)
100
100
  return proc.returncode
101
101
 
102
- @ap.command(
102
+ @ap.cmd(
103
103
  ap.arg('dir', nargs='?'),
104
104
  ap.arg('--clion', action='store_true'),
105
105
  )
omdev/pyproject/cli.py CHANGED
@@ -35,7 +35,7 @@ import typing as ta
35
35
 
36
36
  from omlish.argparse.cli import ArgparseCli
37
37
  from omlish.argparse.cli import argparse_arg
38
- from omlish.argparse.cli import argparse_command
38
+ from omlish.argparse.cli import argparse_cmd
39
39
  from omlish.asyncs.asyncio.subprocesses import asyncio_subprocesses
40
40
  from omlish.lite.cached import cached_nullary
41
41
  from omlish.lite.check import check
@@ -141,7 +141,7 @@ class Run:
141
141
  class PyprojectCli(ArgparseCli):
142
142
  _docker_container = argparse_arg('--_docker_container', help=argparse.SUPPRESS)
143
143
 
144
- @argparse_command(
144
+ @argparse_cmd(
145
145
  argparse_arg('name'),
146
146
  argparse_arg('-e', '--docker-env', action='append'),
147
147
  argparse_arg('cmd', nargs='?'),
@@ -223,7 +223,7 @@ class PyprojectCli(ArgparseCli):
223
223
  else:
224
224
  raise Exception(f'unknown subcommand: {cmd}')
225
225
 
226
- @argparse_command(
226
+ @argparse_cmd(
227
227
  argparse_arg('-b', '--build', action='store_true'),
228
228
  argparse_arg('-r', '--revision', action='store_true'),
229
229
  argparse_arg('-j', '--jobs', type=int),
@@ -4,15 +4,14 @@ import typing as ta
4
4
 
5
5
  from omlish.lite.marshal import unmarshal_obj
6
6
 
7
+ from ..interp.venvs import InterpVenvConfig
8
+
7
9
 
8
10
  @dc.dataclass(frozen=True)
9
- class VenvConfig:
11
+ class VenvConfig(InterpVenvConfig):
10
12
  inherits: ta.Optional[ta.Sequence[str]] = None
11
- interp: ta.Optional[str] = None
12
- requires: ta.Optional[ta.List[str]] = None
13
13
  docker: ta.Optional[str] = None
14
14
  srcs: ta.Optional[ta.List[str]] = None
15
- use_uv: ta.Optional[bool] = None
16
15
 
17
16
 
18
17
  @dc.dataclass(frozen=True)
@@ -0,0 +1,12 @@
1
+ # ruff: noqa: UP006 UP007
2
+ import typing as ta
3
+
4
+ from omlish.lite.inject import InjectorBindingOrBindings
5
+ from omlish.lite.inject import InjectorBindings
6
+ from omlish.lite.inject import inj
7
+
8
+
9
+ def bind_pyproject() -> InjectorBindings:
10
+ lst: ta.List[InjectorBindingOrBindings] = []
11
+
12
+ return inj.as_bindings(*lst)
omdev/pyproject/venvs.py CHANGED
@@ -3,14 +3,12 @@ import glob
3
3
  import os.path
4
4
  import typing as ta
5
5
 
6
- from omlish.asyncs.asyncio.subprocesses import asyncio_subprocesses
7
6
  from omlish.lite.cached import async_cached_nullary
8
7
  from omlish.lite.cached import cached_nullary
9
- from omlish.lite.check import check
10
8
  from omlish.lite.logs import log
11
9
 
12
- from ..interp.default import get_default_interp_resolver
13
- from ..interp.types import InterpSpecifier
10
+ from ..interp.venvs import InterpVenv
11
+ from ..interp.venvs import InterpVenvRequirementsProcessor
14
12
  from .configs import VenvConfig
15
13
  from .reqs import RequirementsRewriter
16
14
 
@@ -38,60 +36,26 @@ class Venv:
38
36
  def dir_name(self) -> str:
39
37
  return os.path.join(self.DIR_NAME, self._name)
40
38
 
41
- @async_cached_nullary
42
- async def interp_exe(self) -> str:
43
- i = InterpSpecifier.parse(check.not_none(self._cfg.interp))
44
- return check.not_none(await get_default_interp_resolver().resolve(i, install=True)).exe
39
+ @cached_nullary
40
+ def _iv(self) -> InterpVenv:
41
+ rr = RequirementsRewriter(self._name)
42
+
43
+ return InterpVenv(
44
+ self.dir_name,
45
+ self._cfg,
46
+ requirements_processor=InterpVenvRequirementsProcessor(
47
+ lambda iv, reqs: [rr.rewrite(req) for req in reqs] # noqa
48
+ ),
49
+ log=log,
50
+ )
45
51
 
46
52
  @cached_nullary
47
53
  def exe(self) -> str:
48
- ve = os.path.join(self.dir_name, 'bin/python')
49
- if not os.path.isfile(ve):
50
- raise Exception(f'venv exe {ve} does not exist or is not a file!')
51
- return ve
54
+ return self._iv().exe()
52
55
 
53
56
  @async_cached_nullary
54
57
  async def create(self) -> bool:
55
- if os.path.exists(dn := self.dir_name):
56
- if not os.path.isdir(dn):
57
- raise Exception(f'{dn} exists but is not a directory!')
58
- return False
59
-
60
- log.info('Using interpreter %s', (ie := await self.interp_exe()))
61
- await asyncio_subprocesses.check_call(ie, '-m', 'venv', dn)
62
-
63
- ve = self.exe()
64
- uv = self._cfg.use_uv
65
-
66
- await asyncio_subprocesses.check_call(
67
- ve,
68
- '-m', 'pip',
69
- 'install', '-v', '--upgrade',
70
- 'pip',
71
- 'setuptools',
72
- 'wheel',
73
- *(['uv'] if uv else []),
74
- )
75
-
76
- if sr := self._cfg.requires:
77
- rr = RequirementsRewriter(self._name)
78
- reqs = [rr.rewrite(req) for req in sr]
79
-
80
- # TODO: automatically try slower uv download when it fails? lol
81
- # Caused by: Failed to download distribution due to network timeout. Try increasing UV_HTTP_TIMEOUT (current value: 30s). # noqa
82
- # UV_CONCURRENT_DOWNLOADS=4 UV_HTTP_TIMEOUT=3600
83
-
84
- await asyncio_subprocesses.check_call(
85
- ve,
86
- '-m',
87
- *(['uv'] if uv else []),
88
- 'pip',
89
- 'install',
90
- *([] if uv else ['-v']),
91
- *reqs,
92
- )
93
-
94
- return True
58
+ return await self._iv().create()
95
59
 
96
60
  @staticmethod
97
61
  def _resolve_srcs(raw: ta.List[str]) -> ta.List[str]: