omdev 0.0.0.dev224__py3-none-any.whl → 0.0.0.dev225__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.
@@ -128,7 +128,7 @@ InjectorProviderFn = ta.Callable[['Injector'], ta.Any]
128
128
  InjectorProviderFnMap = ta.Mapping['InjectorKey', 'InjectorProviderFn']
129
129
  InjectorBindingOrBindings = ta.Union['InjectorBinding', 'InjectorBindings']
130
130
 
131
- # ../../omlish/subprocesses.py
131
+ # ../../omlish/subprocesses/base.py
132
132
  SubprocessChannelOption = ta.Literal['pipe', 'stdout', 'devnull'] # ta.TypeAlias
133
133
 
134
134
 
@@ -5625,6 +5625,98 @@ class JsonLogFormatter(logging.Formatter):
5625
5625
  return self._json_dumps(dct)
5626
5626
 
5627
5627
 
5628
+ ########################################
5629
+ # ../../../omlish/subprocesses/run.py
5630
+
5631
+
5632
+ ##
5633
+
5634
+
5635
+ @dc.dataclass(frozen=True)
5636
+ class SubprocessRunOutput(ta.Generic[T]):
5637
+ proc: T
5638
+
5639
+ returncode: int # noqa
5640
+
5641
+ stdout: ta.Optional[bytes] = None
5642
+ stderr: ta.Optional[bytes] = None
5643
+
5644
+
5645
+ ##
5646
+
5647
+
5648
+ @dc.dataclass(frozen=True)
5649
+ class SubprocessRun:
5650
+ cmd: ta.Sequence[str]
5651
+ input: ta.Any = None
5652
+ timeout: ta.Optional[float] = None
5653
+ check: bool = False
5654
+ capture_output: ta.Optional[bool] = None
5655
+ kwargs: ta.Optional[ta.Mapping[str, ta.Any]] = None
5656
+
5657
+ @classmethod
5658
+ def of(
5659
+ cls,
5660
+ *cmd: str,
5661
+ input: ta.Any = None, # noqa
5662
+ timeout: ta.Optional[float] = None,
5663
+ check: bool = False, # noqa
5664
+ capture_output: ta.Optional[bool] = None,
5665
+ **kwargs: ta.Any,
5666
+ ) -> 'SubprocessRun':
5667
+ return cls(
5668
+ cmd=cmd,
5669
+ input=input,
5670
+ timeout=timeout,
5671
+ check=check,
5672
+ capture_output=capture_output,
5673
+ kwargs=kwargs,
5674
+ )
5675
+
5676
+ #
5677
+
5678
+ _DEFAULT_SUBPROCESSES: ta.ClassVar[ta.Optional[ta.Any]] = None # AbstractSubprocesses
5679
+
5680
+ def run(
5681
+ self,
5682
+ subprocesses: ta.Optional[ta.Any] = None, # AbstractSubprocesses
5683
+ ) -> SubprocessRunOutput:
5684
+ if subprocesses is None:
5685
+ subprocesses = self._DEFAULT_SUBPROCESSES
5686
+ return check.not_none(subprocesses).run_(self) # type: ignore[attr-defined]
5687
+
5688
+ _DEFAULT_ASYNC_SUBPROCESSES: ta.ClassVar[ta.Optional[ta.Any]] = None # AbstractAsyncSubprocesses
5689
+
5690
+ async def async_run(
5691
+ self,
5692
+ async_subprocesses: ta.Optional[ta.Any] = None, # AbstractAsyncSubprocesses
5693
+ ) -> SubprocessRunOutput:
5694
+ if async_subprocesses is None:
5695
+ async_subprocesses = self._DEFAULT_ASYNC_SUBPROCESSES
5696
+ return await check.not_none(async_subprocesses).run_(self) # type: ignore[attr-defined]
5697
+
5698
+
5699
+ ##
5700
+
5701
+
5702
+ class SubprocessRunnable(abc.ABC, ta.Generic[T]):
5703
+ @abc.abstractmethod
5704
+ def make_run(self) -> SubprocessRun:
5705
+ raise NotImplementedError
5706
+
5707
+ @abc.abstractmethod
5708
+ def handle_run_output(self, output: SubprocessRunOutput) -> T:
5709
+ raise NotImplementedError
5710
+
5711
+ #
5712
+
5713
+ def run(self, subprocesses: ta.Optional[ta.Any] = None) -> T: # AbstractSubprocesses
5714
+ return self.handle_run_output(self.make_run().run(subprocesses))
5715
+
5716
+ async def async_run(self, async_subprocesses: ta.Optional[ta.Any] = None) -> T: # AbstractAsyncSubprocesses
5717
+ return self.handle_run_output(await self.make_run().async_run(async_subprocesses))
5718
+
5719
+
5628
5720
  ########################################
5629
5721
  # ../../interp/types.py
5630
5722
 
@@ -5863,23 +5955,7 @@ def configure_standard_logging(
5863
5955
 
5864
5956
 
5865
5957
  ########################################
5866
- # ../../../omlish/subprocesses.py
5867
-
5868
-
5869
- ##
5870
-
5871
-
5872
- # Valid channel type kwarg values:
5873
- # - A special flag negative int
5874
- # - A positive fd int
5875
- # - A file-like object
5876
- # - None
5877
-
5878
- SUBPROCESS_CHANNEL_OPTION_VALUES: ta.Mapping[SubprocessChannelOption, int] = {
5879
- 'pipe': subprocess.PIPE,
5880
- 'stdout': subprocess.STDOUT,
5881
- 'devnull': subprocess.DEVNULL,
5882
- }
5958
+ # ../../../omlish/subprocesses/wrap.py
5883
5959
 
5884
5960
 
5885
5961
  ##
@@ -5899,22 +5975,68 @@ def subprocess_maybe_shell_wrap_exec(*cmd: str) -> ta.Tuple[str, ...]:
5899
5975
  return cmd
5900
5976
 
5901
5977
 
5978
+ ########################################
5979
+ # ../../interp/providers/base.py
5980
+ """
5981
+ TODO:
5982
+ - backends
5983
+ - local builds
5984
+ - deadsnakes?
5985
+ - uv
5986
+ - loose versions
5987
+ """
5988
+
5989
+
5902
5990
  ##
5903
5991
 
5904
5992
 
5905
- def subprocess_close(
5906
- proc: subprocess.Popen,
5907
- timeout: ta.Optional[float] = None,
5908
- ) -> None:
5909
- # TODO: terminate, sleep, kill
5910
- if proc.stdout:
5911
- proc.stdout.close()
5912
- if proc.stderr:
5913
- proc.stderr.close()
5914
- if proc.stdin:
5915
- proc.stdin.close()
5993
+ class InterpProvider(abc.ABC):
5994
+ name: ta.ClassVar[str]
5995
+
5996
+ def __init_subclass__(cls, **kwargs: ta.Any) -> None:
5997
+ super().__init_subclass__(**kwargs)
5998
+ if abc.ABC not in cls.__bases__ and 'name' not in cls.__dict__:
5999
+ sfx = 'InterpProvider'
6000
+ if not cls.__name__.endswith(sfx):
6001
+ raise NameError(cls)
6002
+ setattr(cls, 'name', snake_case(cls.__name__[:-len(sfx)]))
6003
+
6004
+ @abc.abstractmethod
6005
+ def get_installed_versions(self, spec: InterpSpecifier) -> ta.Awaitable[ta.Sequence[InterpVersion]]:
6006
+ raise NotImplementedError
6007
+
6008
+ @abc.abstractmethod
6009
+ def get_installed_version(self, version: InterpVersion) -> ta.Awaitable[Interp]:
6010
+ raise NotImplementedError
6011
+
6012
+ async def get_installable_versions(self, spec: InterpSpecifier) -> ta.Sequence[InterpVersion]:
6013
+ return []
6014
+
6015
+ async def install_version(self, version: InterpVersion) -> Interp:
6016
+ raise TypeError
6017
+
6018
+
6019
+ InterpProviders = ta.NewType('InterpProviders', ta.Sequence[InterpProvider])
6020
+
6021
+
6022
+ ########################################
6023
+ # ../../../omlish/subprocesses/base.py
6024
+
6025
+
6026
+ ##
6027
+
6028
+
6029
+ # Valid channel type kwarg values:
6030
+ # - A special flag negative int
6031
+ # - A positive fd int
6032
+ # - A file-like object
6033
+ # - None
5916
6034
 
5917
- proc.wait(timeout)
6035
+ SUBPROCESS_CHANNEL_OPTION_VALUES: ta.Mapping[SubprocessChannelOption, int] = {
6036
+ 'pipe': subprocess.PIPE,
6037
+ 'stdout': subprocess.STDOUT,
6038
+ 'devnull': subprocess.DEVNULL,
6039
+ }
5918
6040
 
5919
6041
 
5920
6042
  ##
@@ -6101,46 +6223,190 @@ class BaseSubprocesses(abc.ABC): # noqa
6101
6223
  return e
6102
6224
 
6103
6225
 
6104
- ##
6226
+ ########################################
6227
+ # ../../interp/resolvers.py
6105
6228
 
6106
6229
 
6107
6230
  @dc.dataclass(frozen=True)
6108
- class SubprocessRun:
6109
- cmd: ta.Sequence[str]
6110
- input: ta.Any = None
6111
- timeout: ta.Optional[float] = None
6112
- check: bool = False
6113
- capture_output: ta.Optional[bool] = None
6114
- kwargs: ta.Optional[ta.Mapping[str, ta.Any]] = None
6231
+ class InterpResolverProviders:
6232
+ providers: ta.Sequence[ta.Tuple[str, InterpProvider]]
6115
6233
 
6116
- @classmethod
6117
- def of(
6118
- cls,
6234
+
6235
+ class InterpResolver:
6236
+ def __init__(
6237
+ self,
6238
+ providers: InterpResolverProviders,
6239
+ ) -> None:
6240
+ super().__init__()
6241
+
6242
+ self._providers: ta.Mapping[str, InterpProvider] = collections.OrderedDict(providers.providers)
6243
+
6244
+ async def _resolve_installed(self, spec: InterpSpecifier) -> ta.Optional[ta.Tuple[InterpProvider, InterpVersion]]:
6245
+ lst = [
6246
+ (i, si)
6247
+ for i, p in enumerate(self._providers.values())
6248
+ for si in await p.get_installed_versions(spec)
6249
+ if spec.contains(si)
6250
+ ]
6251
+
6252
+ slst = sorted(lst, key=lambda t: (-t[0], t[1].version))
6253
+ if not slst:
6254
+ return None
6255
+
6256
+ bi, bv = slst[-1]
6257
+ bp = list(self._providers.values())[bi]
6258
+ return (bp, bv)
6259
+
6260
+ async def resolve(
6261
+ self,
6262
+ spec: InterpSpecifier,
6263
+ *,
6264
+ install: bool = False,
6265
+ ) -> ta.Optional[Interp]:
6266
+ tup = await self._resolve_installed(spec)
6267
+ if tup is not None:
6268
+ bp, bv = tup
6269
+ return await bp.get_installed_version(bv)
6270
+
6271
+ if not install:
6272
+ return None
6273
+
6274
+ tp = list(self._providers.values())[0] # noqa
6275
+
6276
+ sv = sorted(
6277
+ [s for s in await tp.get_installable_versions(spec) if s in spec],
6278
+ key=lambda s: s.version,
6279
+ )
6280
+ if not sv:
6281
+ return None
6282
+
6283
+ bv = sv[-1]
6284
+ return await tp.install_version(bv)
6285
+
6286
+ async def list(self, spec: InterpSpecifier) -> None:
6287
+ print('installed:')
6288
+ for n, p in self._providers.items():
6289
+ lst = [
6290
+ si
6291
+ for si in await p.get_installed_versions(spec)
6292
+ if spec.contains(si)
6293
+ ]
6294
+ if lst:
6295
+ print(f' {n}')
6296
+ for si in lst:
6297
+ print(f' {si}')
6298
+
6299
+ print()
6300
+
6301
+ print('installable:')
6302
+ for n, p in self._providers.items():
6303
+ lst = [
6304
+ si
6305
+ for si in await p.get_installable_versions(spec)
6306
+ if spec.contains(si)
6307
+ ]
6308
+ if lst:
6309
+ print(f' {n}')
6310
+ for si in lst:
6311
+ print(f' {si}')
6312
+
6313
+
6314
+ ########################################
6315
+ # ../../../omlish/subprocesses/async_.py
6316
+
6317
+
6318
+ ##
6319
+
6320
+
6321
+ class AbstractAsyncSubprocesses(BaseSubprocesses):
6322
+ @abc.abstractmethod
6323
+ async def run_(self, run: SubprocessRun) -> SubprocessRunOutput:
6324
+ raise NotImplementedError
6325
+
6326
+ def run(
6327
+ self,
6328
+ *cmd: str,
6329
+ input: ta.Any = None, # noqa
6330
+ timeout: ta.Optional[float] = None,
6331
+ check: bool = False,
6332
+ capture_output: ta.Optional[bool] = None,
6333
+ **kwargs: ta.Any,
6334
+ ) -> ta.Awaitable[SubprocessRunOutput]:
6335
+ return self.run_(SubprocessRun(
6336
+ cmd=cmd,
6337
+ input=input,
6338
+ timeout=timeout,
6339
+ check=check,
6340
+ capture_output=capture_output,
6341
+ kwargs=kwargs,
6342
+ ))
6343
+
6344
+ #
6345
+
6346
+ @abc.abstractmethod
6347
+ async def check_call(
6348
+ self,
6349
+ *cmd: str,
6350
+ stdout: ta.Any = sys.stderr,
6351
+ **kwargs: ta.Any,
6352
+ ) -> None:
6353
+ raise NotImplementedError
6354
+
6355
+ @abc.abstractmethod
6356
+ async def check_output(
6357
+ self,
6358
+ *cmd: str,
6359
+ **kwargs: ta.Any,
6360
+ ) -> bytes:
6361
+ raise NotImplementedError
6362
+
6363
+ #
6364
+
6365
+ async def check_output_str(
6366
+ self,
6367
+ *cmd: str,
6368
+ **kwargs: ta.Any,
6369
+ ) -> str:
6370
+ return (await self.check_output(*cmd, **kwargs)).decode().strip()
6371
+
6372
+ #
6373
+
6374
+ async def try_call(
6375
+ self,
6376
+ *cmd: str,
6377
+ **kwargs: ta.Any,
6378
+ ) -> bool:
6379
+ if isinstance(await self.async_try_fn(self.check_call, *cmd, **kwargs), Exception):
6380
+ return False
6381
+ else:
6382
+ return True
6383
+
6384
+ async def try_output(
6385
+ self,
6386
+ *cmd: str,
6387
+ **kwargs: ta.Any,
6388
+ ) -> ta.Optional[bytes]:
6389
+ if isinstance(ret := await self.async_try_fn(self.check_output, *cmd, **kwargs), Exception):
6390
+ return None
6391
+ else:
6392
+ return ret
6393
+
6394
+ async def try_output_str(
6395
+ self,
6119
6396
  *cmd: str,
6120
- input: ta.Any = None, # noqa
6121
- timeout: ta.Optional[float] = None,
6122
- check: bool = False,
6123
- capture_output: ta.Optional[bool] = None,
6124
6397
  **kwargs: ta.Any,
6125
- ) -> 'SubprocessRun':
6126
- return cls(
6127
- cmd=cmd,
6128
- input=input,
6129
- timeout=timeout,
6130
- check=check,
6131
- capture_output=capture_output,
6132
- kwargs=kwargs,
6133
- )
6398
+ ) -> ta.Optional[str]:
6399
+ if (ret := await self.try_output(*cmd, **kwargs)) is None:
6400
+ return None
6401
+ else:
6402
+ return ret.decode().strip()
6134
6403
 
6135
6404
 
6136
- @dc.dataclass(frozen=True)
6137
- class SubprocessRunOutput(ta.Generic[T]):
6138
- proc: T
6405
+ ########################################
6406
+ # ../../../omlish/subprocesses/sync.py
6139
6407
 
6140
- returncode: int # noqa
6141
6408
 
6142
- stdout: ta.Optional[bytes] = None
6143
- stderr: ta.Optional[bytes] = None
6409
+ ##
6144
6410
 
6145
6411
 
6146
6412
  class AbstractSubprocesses(BaseSubprocesses, abc.ABC):
@@ -6232,14 +6498,15 @@ class AbstractSubprocesses(BaseSubprocesses, abc.ABC):
6232
6498
 
6233
6499
  class Subprocesses(AbstractSubprocesses):
6234
6500
  def run_(self, run: SubprocessRun) -> SubprocessRunOutput[subprocess.CompletedProcess]:
6235
- proc = subprocess.run(
6236
- run.cmd,
6237
- input=run.input,
6238
- timeout=run.timeout,
6239
- check=run.check,
6240
- capture_output=run.capture_output or False,
6241
- **(run.kwargs or {}),
6242
- )
6501
+ with self.prepare_and_wrap(
6502
+ *run.cmd,
6503
+ input=run.input,
6504
+ timeout=run.timeout,
6505
+ check=run.check,
6506
+ capture_output=run.capture_output or False,
6507
+ **(run.kwargs or {}),
6508
+ ) as (cmd, kwargs):
6509
+ proc = subprocess.run(cmd, **kwargs) # noqa
6243
6510
 
6244
6511
  return SubprocessRunOutput(
6245
6512
  proc=proc,
@@ -6268,94 +6535,12 @@ class Subprocesses(AbstractSubprocesses):
6268
6535
  return subprocess.check_output(cmd, **kwargs)
6269
6536
 
6270
6537
 
6271
- subprocesses = Subprocesses()
6272
-
6273
-
6274
6538
  ##
6275
6539
 
6276
6540
 
6277
- class AbstractAsyncSubprocesses(BaseSubprocesses):
6278
- @abc.abstractmethod
6279
- async def run_(self, run: SubprocessRun) -> SubprocessRunOutput:
6280
- raise NotImplementedError
6281
-
6282
- def run(
6283
- self,
6284
- *cmd: str,
6285
- input: ta.Any = None, # noqa
6286
- timeout: ta.Optional[float] = None,
6287
- check: bool = False,
6288
- capture_output: ta.Optional[bool] = None,
6289
- **kwargs: ta.Any,
6290
- ) -> ta.Awaitable[SubprocessRunOutput]:
6291
- return self.run_(SubprocessRun(
6292
- cmd=cmd,
6293
- input=input,
6294
- timeout=timeout,
6295
- check=check,
6296
- capture_output=capture_output,
6297
- kwargs=kwargs,
6298
- ))
6299
-
6300
- #
6301
-
6302
- @abc.abstractmethod
6303
- async def check_call(
6304
- self,
6305
- *cmd: str,
6306
- stdout: ta.Any = sys.stderr,
6307
- **kwargs: ta.Any,
6308
- ) -> None:
6309
- raise NotImplementedError
6310
-
6311
- @abc.abstractmethod
6312
- async def check_output(
6313
- self,
6314
- *cmd: str,
6315
- **kwargs: ta.Any,
6316
- ) -> bytes:
6317
- raise NotImplementedError
6318
-
6319
- #
6320
-
6321
- async def check_output_str(
6322
- self,
6323
- *cmd: str,
6324
- **kwargs: ta.Any,
6325
- ) -> str:
6326
- return (await self.check_output(*cmd, **kwargs)).decode().strip()
6327
-
6328
- #
6329
-
6330
- async def try_call(
6331
- self,
6332
- *cmd: str,
6333
- **kwargs: ta.Any,
6334
- ) -> bool:
6335
- if isinstance(await self.async_try_fn(self.check_call, *cmd, **kwargs), Exception):
6336
- return False
6337
- else:
6338
- return True
6339
-
6340
- async def try_output(
6341
- self,
6342
- *cmd: str,
6343
- **kwargs: ta.Any,
6344
- ) -> ta.Optional[bytes]:
6345
- if isinstance(ret := await self.async_try_fn(self.check_output, *cmd, **kwargs), Exception):
6346
- return None
6347
- else:
6348
- return ret
6541
+ subprocesses = Subprocesses()
6349
6542
 
6350
- async def try_output_str(
6351
- self,
6352
- *cmd: str,
6353
- **kwargs: ta.Any,
6354
- ) -> ta.Optional[str]:
6355
- if (ret := await self.try_output(*cmd, **kwargs)) is None:
6356
- return None
6357
- else:
6358
- return ret.decode().strip()
6543
+ SubprocessRun._DEFAULT_SUBPROCESSES = subprocesses # noqa
6359
6544
 
6360
6545
 
6361
6546
  ########################################
@@ -6404,50 +6589,6 @@ def get_git_revision(
6404
6589
  return dirty_rev + ('-untracked' if has_untracked else '')
6405
6590
 
6406
6591
 
6407
- ########################################
6408
- # ../../interp/providers/base.py
6409
- """
6410
- TODO:
6411
- - backends
6412
- - local builds
6413
- - deadsnakes?
6414
- - uv
6415
- - loose versions
6416
- """
6417
-
6418
-
6419
- ##
6420
-
6421
-
6422
- class InterpProvider(abc.ABC):
6423
- name: ta.ClassVar[str]
6424
-
6425
- def __init_subclass__(cls, **kwargs: ta.Any) -> None:
6426
- super().__init_subclass__(**kwargs)
6427
- if abc.ABC not in cls.__bases__ and 'name' not in cls.__dict__:
6428
- sfx = 'InterpProvider'
6429
- if not cls.__name__.endswith(sfx):
6430
- raise NameError(cls)
6431
- setattr(cls, 'name', snake_case(cls.__name__[:-len(sfx)]))
6432
-
6433
- @abc.abstractmethod
6434
- def get_installed_versions(self, spec: InterpSpecifier) -> ta.Awaitable[ta.Sequence[InterpVersion]]:
6435
- raise NotImplementedError
6436
-
6437
- @abc.abstractmethod
6438
- def get_installed_version(self, version: InterpVersion) -> ta.Awaitable[Interp]:
6439
- raise NotImplementedError
6440
-
6441
- async def get_installable_versions(self, spec: InterpSpecifier) -> ta.Sequence[InterpVersion]:
6442
- return []
6443
-
6444
- async def install_version(self, version: InterpVersion) -> Interp:
6445
- raise TypeError
6446
-
6447
-
6448
- InterpProviders = ta.NewType('InterpProviders', ta.Sequence[InterpProvider])
6449
-
6450
-
6451
6592
  ########################################
6452
6593
  # ../../../omlish/asyncs/asyncio/subprocesses.py
6453
6594
 
@@ -6590,19 +6731,19 @@ class AsyncioSubprocesses(AbstractAsyncSubprocesses):
6590
6731
  timeout: ta.Optional[float] = None,
6591
6732
  **kwargs: ta.Any,
6592
6733
  ) -> ta.AsyncGenerator[asyncio.subprocess.Process, None]:
6593
- fac: ta.Any
6594
- if shell:
6595
- fac = functools.partial(
6596
- asyncio.create_subprocess_shell,
6597
- check.single(cmd),
6598
- )
6599
- else:
6600
- fac = functools.partial(
6601
- asyncio.create_subprocess_exec,
6602
- *cmd,
6603
- )
6604
-
6605
6734
  with self.prepare_and_wrap( *cmd, shell=shell, **kwargs) as (cmd, kwargs): # noqa
6735
+ fac: ta.Any
6736
+ if shell:
6737
+ fac = functools.partial(
6738
+ asyncio.create_subprocess_shell,
6739
+ check.single(cmd),
6740
+ )
6741
+ else:
6742
+ fac = functools.partial(
6743
+ asyncio.create_subprocess_exec,
6744
+ *cmd,
6745
+ )
6746
+
6606
6747
  proc: asyncio.subprocess.Process = await fac(**kwargs)
6607
6748
  try:
6608
6749
  yield proc
@@ -6843,94 +6984,6 @@ class Pyenv:
6843
6984
  return True
6844
6985
 
6845
6986
 
6846
- ########################################
6847
- # ../../interp/resolvers.py
6848
-
6849
-
6850
- @dc.dataclass(frozen=True)
6851
- class InterpResolverProviders:
6852
- providers: ta.Sequence[ta.Tuple[str, InterpProvider]]
6853
-
6854
-
6855
- class InterpResolver:
6856
- def __init__(
6857
- self,
6858
- providers: InterpResolverProviders,
6859
- ) -> None:
6860
- super().__init__()
6861
-
6862
- self._providers: ta.Mapping[str, InterpProvider] = collections.OrderedDict(providers.providers)
6863
-
6864
- async def _resolve_installed(self, spec: InterpSpecifier) -> ta.Optional[ta.Tuple[InterpProvider, InterpVersion]]:
6865
- lst = [
6866
- (i, si)
6867
- for i, p in enumerate(self._providers.values())
6868
- for si in await p.get_installed_versions(spec)
6869
- if spec.contains(si)
6870
- ]
6871
-
6872
- slst = sorted(lst, key=lambda t: (-t[0], t[1].version))
6873
- if not slst:
6874
- return None
6875
-
6876
- bi, bv = slst[-1]
6877
- bp = list(self._providers.values())[bi]
6878
- return (bp, bv)
6879
-
6880
- async def resolve(
6881
- self,
6882
- spec: InterpSpecifier,
6883
- *,
6884
- install: bool = False,
6885
- ) -> ta.Optional[Interp]:
6886
- tup = await self._resolve_installed(spec)
6887
- if tup is not None:
6888
- bp, bv = tup
6889
- return await bp.get_installed_version(bv)
6890
-
6891
- if not install:
6892
- return None
6893
-
6894
- tp = list(self._providers.values())[0] # noqa
6895
-
6896
- sv = sorted(
6897
- [s for s in await tp.get_installable_versions(spec) if s in spec],
6898
- key=lambda s: s.version,
6899
- )
6900
- if not sv:
6901
- return None
6902
-
6903
- bv = sv[-1]
6904
- return await tp.install_version(bv)
6905
-
6906
- async def list(self, spec: InterpSpecifier) -> None:
6907
- print('installed:')
6908
- for n, p in self._providers.items():
6909
- lst = [
6910
- si
6911
- for si in await p.get_installed_versions(spec)
6912
- if spec.contains(si)
6913
- ]
6914
- if lst:
6915
- print(f' {n}')
6916
- for si in lst:
6917
- print(f' {si}')
6918
-
6919
- print()
6920
-
6921
- print('installable:')
6922
- for n, p in self._providers.items():
6923
- lst = [
6924
- si
6925
- for si in await p.get_installable_versions(spec)
6926
- if spec.contains(si)
6927
- ]
6928
- if lst:
6929
- print(f' {n}')
6930
- for si in lst:
6931
- print(f' {si}')
6932
-
6933
-
6934
6987
  ########################################
6935
6988
  # ../../revisions.py
6936
6989
  """