omdev 0.0.0.dev178__py3-none-any.whl → 0.0.0.dev180__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.
Files changed (44) hide show
  1. omdev/.manifests.json +5 -5
  2. omdev/amalg/main.py +1 -0
  3. omdev/cexts/importhook.py +1 -1
  4. omdev/cli/clicli.py +6 -6
  5. omdev/imgur.py +1 -1
  6. omdev/interp/cli.py +44 -43
  7. omdev/interp/default.py +10 -0
  8. omdev/interp/inject.py +54 -0
  9. omdev/interp/inspect.py +0 -3
  10. omdev/interp/providers/__init__.py +0 -0
  11. omdev/interp/{providers.py → providers/base.py} +4 -24
  12. omdev/interp/providers/inject.py +26 -0
  13. omdev/interp/providers/running.py +27 -0
  14. omdev/interp/{system.py → providers/system.py} +27 -15
  15. omdev/interp/pyenv/__init__.py +0 -0
  16. omdev/interp/pyenv/inject.py +21 -0
  17. omdev/interp/{pyenv.py → pyenv/pyenv.py} +24 -23
  18. omdev/interp/resolvers.py +7 -22
  19. omdev/interp/types.py +12 -0
  20. omdev/interp/uv/__init__.py +0 -0
  21. omdev/interp/uv/inject.py +12 -0
  22. omdev/interp/{uv.py → uv/uv.py} +4 -4
  23. omdev/magic/__main__.py +11 -0
  24. omdev/magic/cli.py +54 -0
  25. omdev/magic/find.py +0 -45
  26. omdev/pycharm/cli.py +3 -3
  27. omdev/pyproject/cli.py +3 -3
  28. omdev/pyproject/venvs.py +2 -2
  29. omdev/scripts/interp.py +1968 -466
  30. omdev/scripts/pyproject.py +3320 -2093
  31. omdev/tools/doc.py +2 -2
  32. omdev/tools/docker.py +8 -8
  33. omdev/tools/git.py +7 -7
  34. omdev/tools/notebook.py +1 -1
  35. omdev/tools/pip.py +4 -4
  36. omdev/tools/prof.py +1 -1
  37. omdev/tools/sqlrepl.py +1 -1
  38. {omdev-0.0.0.dev178.dist-info → omdev-0.0.0.dev180.dist-info}/METADATA +2 -2
  39. {omdev-0.0.0.dev178.dist-info → omdev-0.0.0.dev180.dist-info}/RECORD +44 -33
  40. /omdev/interp/{standalone.py → providers/standalone.py} +0 -0
  41. {omdev-0.0.0.dev178.dist-info → omdev-0.0.0.dev180.dist-info}/LICENSE +0 -0
  42. {omdev-0.0.0.dev178.dist-info → omdev-0.0.0.dev180.dist-info}/WHEEL +0 -0
  43. {omdev-0.0.0.dev178.dist-info → omdev-0.0.0.dev180.dist-info}/entry_points.txt +0 -0
  44. {omdev-0.0.0.dev178.dist-info → omdev-0.0.0.dev180.dist-info}/top_level.txt +0 -0
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/amalg/main.py CHANGED
@@ -5,6 +5,7 @@ Conventions:
5
5
 
6
6
  TODO:
7
7
  - !! check only importing lite code
8
+ - check no rel impots
8
9
  - !! strip manifests? or relegate them to a separate tiny module ala __main__.py?
9
10
  - # @omlish-no-amalg ? in cli.types? will strip stmt (more than 1 line) following @manifest, so shouldn't import
10
11
  - more sanity checks lol
omdev/cexts/importhook.py CHANGED
@@ -26,7 +26,7 @@ def load_dynamic(name: str, path: str) -> types.ModuleType:
26
26
  spec = importlib.machinery.ModuleSpec(name=name, loader=loader, origin=path)
27
27
 
28
28
  import importlib._bootstrap # FIXME: # noqa
29
- return importlib._bootstrap._load(spec) # noqa
29
+ return importlib._bootstrap._load(spec) # type: ignore # noqa
30
30
 
31
31
 
32
32
  ##
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
@@ -7,66 +7,67 @@ TODO:
7
7
  - https://github.com/asdf-vm/asdf support (instead of pyenv) ?
8
8
  - colon sep provider name prefix - pyenv:3.12
9
9
  """
10
- import argparse
11
10
  import asyncio
12
11
  import typing as ta
13
12
 
13
+ from omlish.argparse.cli import ArgparseCli
14
+ from omlish.argparse.cli import argparse_arg
15
+ from omlish.argparse.cli import argparse_cmd
16
+ from omlish.lite.cached import cached_nullary
14
17
  from omlish.lite.check import check
18
+ from omlish.lite.inject import Injector
19
+ from omlish.lite.inject import inj
15
20
  from omlish.lite.runtime import check_lite_runtime_version
16
21
  from omlish.logs.standard import configure_standard_logging
17
22
 
18
- from .resolvers import DEFAULT_INTERP_RESOLVER
19
- from .resolvers import INTERP_PROVIDER_TYPES_BY_NAME
23
+ from .inject import bind_interp
20
24
  from .resolvers import InterpResolver
25
+ from .resolvers import InterpResolverProviders
21
26
  from .types import InterpSpecifier
22
27
 
23
28
 
24
- async def _list_cmd(args) -> None:
25
- r = DEFAULT_INTERP_RESOLVER
26
- s = InterpSpecifier.parse(args.version)
27
- await r.list(s)
28
-
29
-
30
- async def _resolve_cmd(args) -> None:
31
- if args.provider:
32
- p = INTERP_PROVIDER_TYPES_BY_NAME[args.provider]()
33
- r = InterpResolver([(p.name, p)])
34
- else:
35
- r = DEFAULT_INTERP_RESOLVER
36
- s = InterpSpecifier.parse(args.version)
37
- print(check.not_none(await r.resolve(s, install=bool(args.install))).exe)
38
-
39
-
40
- def _build_parser() -> argparse.ArgumentParser:
41
- parser = argparse.ArgumentParser()
42
-
43
- subparsers = parser.add_subparsers()
44
-
45
- parser_list = subparsers.add_parser('list')
46
- parser_list.add_argument('version')
47
- parser_list.add_argument('-d', '--debug', action='store_true')
48
- parser_list.set_defaults(func=_list_cmd)
49
-
50
- parser_resolve = subparsers.add_parser('resolve')
51
- parser_resolve.add_argument('version')
52
- parser_resolve.add_argument('-p', '--provider')
53
- parser_resolve.add_argument('-d', '--debug', action='store_true')
54
- parser_resolve.add_argument('-i', '--install', action='store_true')
55
- parser_resolve.set_defaults(func=_resolve_cmd)
56
-
57
- return parser
29
+ class InterpCli(ArgparseCli):
30
+ @cached_nullary
31
+ def injector(self) -> Injector:
32
+ return inj.create_injector(bind_interp())
33
+
34
+ @cached_nullary
35
+ def providers(self) -> InterpResolverProviders:
36
+ return self.injector()[InterpResolverProviders]
37
+
38
+ #
39
+
40
+ @argparse_cmd(
41
+ argparse_arg('version'),
42
+ argparse_arg('-d', '--debug', action='store_true'),
43
+ )
44
+ async def list(self) -> None:
45
+ r = InterpResolver(self.providers())
46
+ s = InterpSpecifier.parse(self.args.version)
47
+ await r.list(s)
48
+
49
+ @argparse_cmd(
50
+ argparse_arg('version'),
51
+ argparse_arg('-p', '--provider'),
52
+ argparse_arg('-d', '--debug', action='store_true'),
53
+ argparse_arg('-i', '--install', action='store_true'),
54
+ )
55
+ async def resolve(self) -> None:
56
+ if self.args.provider:
57
+ p = check.single([p for n, p in self.providers().providers if n == self.args.provider])
58
+ r = InterpResolver(InterpResolverProviders([(p.name, p)]))
59
+ else:
60
+ r = InterpResolver(self.providers())
61
+ s = InterpSpecifier.parse(self.args.version)
62
+ print(check.not_none(await r.resolve(s, install=bool(self.args.install))).exe)
58
63
 
59
64
 
60
65
  async def _async_main(argv: ta.Optional[ta.Sequence[str]] = None) -> None:
61
66
  check_lite_runtime_version()
62
67
  configure_standard_logging()
63
68
 
64
- parser = _build_parser()
65
- args = parser.parse_args(argv)
66
- if not getattr(args, 'func', None):
67
- parser.print_help()
68
- else:
69
- await args.func(args)
69
+ cli = ArgparseCli(argv)
70
+ await cli.async_cli_run()
70
71
 
71
72
 
72
73
  def _main(argv: ta.Optional[ta.Sequence[str]] = None) -> None:
@@ -0,0 +1,10 @@
1
+ from omlish.lite.cached import cached_nullary
2
+ from omlish.lite.inject import inj
3
+
4
+ from .inject import bind_interp
5
+ from .resolvers import InterpResolver
6
+
7
+
8
+ @cached_nullary
9
+ def get_default_interp_resolver() -> InterpResolver:
10
+ return inj.create_injector(bind_interp())[InterpResolver]
omdev/interp/inject.py ADDED
@@ -0,0 +1,54 @@
1
+ # ruff: noqa: UP006 UP007
2
+ import typing as ta
3
+
4
+ from omlish.lite.inject import Injector
5
+ from omlish.lite.inject import InjectorBindingOrBindings
6
+ from omlish.lite.inject import InjectorBindings
7
+ from omlish.lite.inject import inj
8
+
9
+ from .inspect import InterpInspector
10
+ from .providers.inject import bind_interp_providers
11
+ from .providers.running import RunningInterpProvider
12
+ from .providers.system import SystemInterpProvider
13
+ from .pyenv.inject import bind_interp_pyenv
14
+ from .pyenv.pyenv import PyenvInterpProvider
15
+ from .resolvers import InterpResolver
16
+ from .resolvers import InterpResolverProviders
17
+ from .uv.inject import bind_interp_uv
18
+
19
+
20
+ def bind_interp() -> InjectorBindings:
21
+ lst: ta.List[InjectorBindingOrBindings] = [
22
+ bind_interp_providers(),
23
+
24
+ bind_interp_pyenv(),
25
+
26
+ bind_interp_uv(),
27
+
28
+ inj.bind(InterpInspector, singleton=True),
29
+ ]
30
+
31
+ #
32
+
33
+ def provide_interp_resolver_providers(injector: Injector) -> InterpResolverProviders:
34
+ # FIXME: lol
35
+ rps: ta.List[ta.Any] = [
36
+ injector.provide(c)
37
+ for c in [
38
+ PyenvInterpProvider,
39
+ RunningInterpProvider,
40
+ SystemInterpProvider,
41
+ ]
42
+ ]
43
+
44
+ return InterpResolverProviders([(rp.name, rp) for rp in rps])
45
+
46
+ lst.append(inj.bind(provide_interp_resolver_providers, singleton=True))
47
+
48
+ lst.extend([
49
+ inj.bind(InterpResolver, singleton=True),
50
+ ])
51
+
52
+ #
53
+
54
+ return inj.as_bindings(*lst)
omdev/interp/inspect.py CHANGED
@@ -99,6 +99,3 @@ class InterpInspector:
99
99
  ret = None
100
100
  self._cache[exe] = ret
101
101
  return ret
102
-
103
-
104
- INTERP_INSPECTOR = InterpInspector()
File without changes
@@ -7,16 +7,13 @@ TODO:
7
7
  - loose versions
8
8
  """
9
9
  import abc
10
- import sys
11
10
  import typing as ta
12
11
 
13
- from omlish.lite.cached import cached_nullary
14
12
  from omlish.lite.strings import snake_case
15
13
 
16
- from .inspect import InterpInspector
17
- from .types import Interp
18
- from .types import InterpSpecifier
19
- from .types import InterpVersion
14
+ from ..types import Interp
15
+ from ..types import InterpSpecifier
16
+ from ..types import InterpVersion
20
17
 
21
18
 
22
19
  ##
@@ -48,21 +45,4 @@ class InterpProvider(abc.ABC):
48
45
  raise TypeError
49
46
 
50
47
 
51
- ##
52
-
53
-
54
- class RunningInterpProvider(InterpProvider):
55
- @cached_nullary
56
- def version(self) -> InterpVersion:
57
- return InterpInspector.running().iv
58
-
59
- async def get_installed_versions(self, spec: InterpSpecifier) -> ta.Sequence[InterpVersion]:
60
- return [self.version()]
61
-
62
- async def get_installed_version(self, version: InterpVersion) -> Interp:
63
- if version != self.version():
64
- raise KeyError(version)
65
- return Interp(
66
- exe=sys.executable,
67
- version=self.version(),
68
- )
48
+ InterpProviders = ta.NewType('InterpProviders', ta.Sequence[InterpProvider])
@@ -0,0 +1,26 @@
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
+ from .base import InterpProvider
9
+ from .base import InterpProviders
10
+ from .running import RunningInterpProvider
11
+ from .system import SystemInterpProvider
12
+
13
+
14
+ def bind_interp_providers() -> InjectorBindings:
15
+ lst: ta.List[InjectorBindingOrBindings] = [
16
+ inj.bind_array(InterpProvider),
17
+ inj.bind_array_type(InterpProvider, InterpProviders),
18
+
19
+ inj.bind(RunningInterpProvider, singleton=True),
20
+ inj.bind(InterpProvider, to_key=RunningInterpProvider, array=True),
21
+
22
+ inj.bind(SystemInterpProvider, singleton=True),
23
+ inj.bind(InterpProvider, to_key=SystemInterpProvider, array=True),
24
+ ]
25
+
26
+ return inj.as_bindings(*lst)
@@ -0,0 +1,27 @@
1
+ import sys
2
+ import typing as ta
3
+
4
+ from omlish.lite.cached import cached_nullary
5
+
6
+ from ..inspect import InterpInspector
7
+ from ..types import Interp
8
+ from ..types import InterpSpecifier
9
+ from ..types import InterpVersion
10
+ from .base import InterpProvider
11
+
12
+
13
+ class RunningInterpProvider(InterpProvider):
14
+ @cached_nullary
15
+ def version(self) -> InterpVersion:
16
+ return InterpInspector.running().iv
17
+
18
+ async def get_installed_versions(self, spec: InterpSpecifier) -> ta.Sequence[InterpVersion]:
19
+ return [self.version()]
20
+
21
+ async def get_installed_version(self, version: InterpVersion) -> Interp:
22
+ if version != self.version():
23
+ raise KeyError(version)
24
+ return Interp(
25
+ exe=sys.executable,
26
+ version=self.version(),
27
+ )
@@ -10,27 +10,39 @@ import re
10
10
  import typing as ta
11
11
 
12
12
  from omlish.lite.cached import cached_nullary
13
+ from omlish.lite.check import check
13
14
  from omlish.lite.logs import log
14
15
 
15
- from ..packaging.versions import InvalidVersion
16
- from .inspect import INTERP_INSPECTOR
17
- from .inspect import InterpInspector
18
- from .providers import InterpProvider
19
- from .types import Interp
20
- from .types import InterpSpecifier
21
- from .types import InterpVersion
16
+ from ...packaging.versions import InvalidVersion
17
+ from ..inspect import InterpInspector
18
+ from ..types import Interp
19
+ from ..types import InterpSpecifier
20
+ from ..types import InterpVersion
21
+ from .base import InterpProvider
22
22
 
23
23
 
24
24
  ##
25
25
 
26
26
 
27
- @dc.dataclass(frozen=True)
28
27
  class SystemInterpProvider(InterpProvider):
29
- cmd: str = 'python3'
30
- path: ta.Optional[str] = None
28
+ @dc.dataclass(frozen=True)
29
+ class Options:
30
+ cmd: str = 'python3' # FIXME: unused lol
31
+ path: ta.Optional[str] = None
31
32
 
32
- inspect: bool = False
33
- inspector: InterpInspector = INTERP_INSPECTOR
33
+ inspect: bool = False
34
+
35
+ def __init__(
36
+ self,
37
+ options: Options = Options(),
38
+ *,
39
+ inspector: ta.Optional[InterpInspector] = None,
40
+ ) -> None:
41
+ super().__init__()
42
+
43
+ self._options = options
44
+
45
+ self._inspector = inspector
34
46
 
35
47
  #
36
48
 
@@ -82,13 +94,13 @@ class SystemInterpProvider(InterpProvider):
82
94
  def exes(self) -> ta.List[str]:
83
95
  return self._re_which(
84
96
  re.compile(r'python3(\.\d+)?'),
85
- path=self.path,
97
+ path=self._options.path,
86
98
  )
87
99
 
88
100
  #
89
101
 
90
102
  async def get_exe_version(self, exe: str) -> ta.Optional[InterpVersion]:
91
- if not self.inspect:
103
+ if not self._options.inspect:
92
104
  s = os.path.basename(exe)
93
105
  if s.startswith('python'):
94
106
  s = s[len('python'):]
@@ -97,7 +109,7 @@ class SystemInterpProvider(InterpProvider):
97
109
  return InterpVersion.parse(s)
98
110
  except InvalidVersion:
99
111
  pass
100
- ii = await self.inspector.inspect(exe)
112
+ ii = await check.not_none(self._inspector).inspect(exe)
101
113
  return ii.iv if ii is not None else None
102
114
 
103
115
  async def exe_versions(self) -> ta.Sequence[ta.Tuple[str, InterpVersion]]:
File without changes
@@ -0,0 +1,21 @@
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
+ from ..providers.base import InterpProvider
9
+ from .pyenv import Pyenv
10
+ from .pyenv import PyenvInterpProvider
11
+
12
+
13
+ def bind_interp_pyenv() -> InjectorBindings:
14
+ lst: ta.List[InjectorBindingOrBindings] = [
15
+ inj.bind(Pyenv, singleton=True),
16
+
17
+ inj.bind(PyenvInterpProvider, singleton=True),
18
+ inj.bind(InterpProvider, to_key=PyenvInterpProvider, array=True),
19
+ ]
20
+
21
+ return inj.as_bindings(*lst)
@@ -24,15 +24,14 @@ from omlish.lite.cached import cached_nullary
24
24
  from omlish.lite.check import check
25
25
  from omlish.lite.logs import log
26
26
 
27
- from ..packaging.versions import InvalidVersion
28
- from ..packaging.versions import Version
29
- from .inspect import INTERP_INSPECTOR
30
- from .inspect import InterpInspector
31
- from .providers import InterpProvider
32
- from .types import Interp
33
- from .types import InterpOpts
34
- from .types import InterpSpecifier
35
- from .types import InterpVersion
27
+ from ...packaging.versions import InvalidVersion
28
+ from ...packaging.versions import Version
29
+ from ..inspect import InterpInspector
30
+ from ..providers.base import InterpProvider
31
+ from ..types import Interp
32
+ from ..types import InterpOpts
33
+ from ..types import InterpSpecifier
34
+ from ..types import InterpVersion
36
35
 
37
36
 
38
37
  ##
@@ -251,9 +250,10 @@ class PyenvVersionInstaller:
251
250
  opts: ta.Optional[PyenvInstallOpts] = None,
252
251
  interp_opts: InterpOpts = InterpOpts(),
253
252
  *,
253
+ pyenv: Pyenv,
254
+
254
255
  install_name: ta.Optional[str] = None,
255
256
  no_default_opts: bool = False,
256
- pyenv: Pyenv = Pyenv(),
257
257
  ) -> None:
258
258
  super().__init__()
259
259
 
@@ -343,26 +343,26 @@ class PyenvVersionInstaller:
343
343
 
344
344
 
345
345
  class PyenvInterpProvider(InterpProvider):
346
- def __init__(
347
- self,
348
- pyenv: Pyenv = Pyenv(),
346
+ @dc.dataclass(frozen=True)
347
+ class Options:
348
+ inspect: bool = False
349
349
 
350
- inspect: bool = False,
351
- inspector: InterpInspector = INTERP_INSPECTOR,
350
+ try_update: bool = False
352
351
 
352
+ def __init__(
353
+ self,
354
+ options: Options = Options(),
353
355
  *,
354
-
355
- try_update: bool = False,
356
+ pyenv: Pyenv,
357
+ inspector: InterpInspector,
356
358
  ) -> None:
357
359
  super().__init__()
358
360
 
359
- self._pyenv = pyenv
361
+ self._options = options
360
362
 
361
- self._inspect = inspect
363
+ self._pyenv = pyenv
362
364
  self._inspector = inspector
363
365
 
364
- self._try_update = try_update
365
-
366
366
  #
367
367
 
368
368
  @staticmethod
@@ -387,7 +387,7 @@ class PyenvInterpProvider(InterpProvider):
387
387
 
388
388
  async def _make_installed(self, vn: str, ep: str) -> ta.Optional[Installed]:
389
389
  iv: ta.Optional[InterpVersion]
390
- if self._inspect:
390
+ if self._options.inspect:
391
391
  try:
392
392
  iv = check.not_none(await self._inspector.inspect(ep)).iv
393
393
  except Exception as e: # noqa
@@ -443,7 +443,7 @@ class PyenvInterpProvider(InterpProvider):
443
443
  async def get_installable_versions(self, spec: InterpSpecifier) -> ta.Sequence[InterpVersion]:
444
444
  lst = await self._get_installable_versions(spec)
445
445
 
446
- if self._try_update and not any(v in spec for v in lst):
446
+ if self._options.try_update and not any(v in spec for v in lst):
447
447
  if self._pyenv.update():
448
448
  lst = await self._get_installable_versions(spec)
449
449
 
@@ -459,6 +459,7 @@ class PyenvInterpProvider(InterpProvider):
459
459
  installer = PyenvVersionInstaller(
460
460
  inst_version,
461
461
  interp_opts=inst_opts,
462
+ pyenv=self._pyenv,
462
463
  )
463
464
 
464
465
  exe = await installer.install()
omdev/interp/resolvers.py CHANGED
@@ -1,32 +1,27 @@
1
1
  # ruff: noqa: UP006 UP007
2
- import abc
3
2
  import collections
3
+ import dataclasses as dc
4
4
  import typing as ta
5
5
 
6
- from omlish.lite.reflect import deep_subclasses
7
-
8
- from .providers import InterpProvider
9
- from .providers import RunningInterpProvider
10
- from .pyenv import PyenvInterpProvider
11
- from .system import SystemInterpProvider
6
+ from .providers.base import InterpProvider
12
7
  from .types import Interp
13
8
  from .types import InterpSpecifier
14
9
  from .types import InterpVersion
15
10
 
16
11
 
17
- INTERP_PROVIDER_TYPES_BY_NAME: ta.Mapping[str, ta.Type[InterpProvider]] = {
18
- cls.name: cls for cls in deep_subclasses(InterpProvider) if abc.ABC not in cls.__bases__ # type: ignore
19
- }
12
+ @dc.dataclass(frozen=True)
13
+ class InterpResolverProviders:
14
+ providers: ta.Sequence[ta.Tuple[str, InterpProvider]]
20
15
 
21
16
 
22
17
  class InterpResolver:
23
18
  def __init__(
24
19
  self,
25
- providers: ta.Sequence[ta.Tuple[str, InterpProvider]],
20
+ providers: InterpResolverProviders,
26
21
  ) -> None:
27
22
  super().__init__()
28
23
 
29
- self._providers: ta.Mapping[str, InterpProvider] = collections.OrderedDict(providers)
24
+ self._providers: ta.Mapping[str, InterpProvider] = collections.OrderedDict(providers.providers)
30
25
 
31
26
  async def _resolve_installed(self, spec: InterpSpecifier) -> ta.Optional[ta.Tuple[InterpProvider, InterpVersion]]:
32
27
  lst = [
@@ -96,13 +91,3 @@ class InterpResolver:
96
91
  print(f' {n}')
97
92
  for si in lst:
98
93
  print(f' {si}')
99
-
100
-
101
- DEFAULT_INTERP_RESOLVER = InterpResolver([(p.name, p) for p in [
102
- # pyenv is preferred to system interpreters as it tends to have more support for things like tkinter
103
- PyenvInterpProvider(try_update=True),
104
-
105
- RunningInterpProvider(),
106
-
107
- SystemInterpProvider(),
108
- ]])
omdev/interp/types.py CHANGED
@@ -8,6 +8,9 @@ from ..packaging.versions import InvalidVersion
8
8
  from ..packaging.versions import Version
9
9
 
10
10
 
11
+ ##
12
+
13
+
11
14
  # See https://peps.python.org/pep-3149/
12
15
  INTERP_OPT_GLYPHS_BY_ATTR: ta.Mapping[str, str] = collections.OrderedDict([
13
16
  ('debug', 'd'),
@@ -39,6 +42,9 @@ class InterpOpts:
39
42
  return s, cls(**kw)
40
43
 
41
44
 
45
+ ##
46
+
47
+
42
48
  @dc.dataclass(frozen=True)
43
49
  class InterpVersion:
44
50
  version: Version
@@ -64,6 +70,9 @@ class InterpVersion:
64
70
  return None
65
71
 
66
72
 
73
+ ##
74
+
75
+
67
76
  @dc.dataclass(frozen=True)
68
77
  class InterpSpecifier:
69
78
  specifier: Specifier
@@ -91,6 +100,9 @@ class InterpSpecifier:
91
100
  return self.contains(iv)
92
101
 
93
102
 
103
+ ##
104
+
105
+
94
106
  @dc.dataclass(frozen=True)
95
107
  class Interp:
96
108
  exe: str