omdev 0.0.0.dev224__py3-none-any.whl → 0.0.0.dev225__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
omdev/scripts/interp.py CHANGED
@@ -87,7 +87,7 @@ InjectorProviderFn = ta.Callable[['Injector'], ta.Any]
87
87
  InjectorProviderFnMap = ta.Mapping['InjectorKey', 'InjectorProviderFn']
88
88
  InjectorBindingOrBindings = ta.Union['InjectorBinding', 'InjectorBindings']
89
89
 
90
- # ../../omlish/subprocesses.py
90
+ # ../../omlish/subprocesses/base.py
91
91
  SubprocessChannelOption = ta.Literal['pipe', 'stdout', 'devnull'] # ta.TypeAlias
92
92
 
93
93
 
@@ -3369,6 +3369,98 @@ class JsonLogFormatter(logging.Formatter):
3369
3369
  return self._json_dumps(dct)
3370
3370
 
3371
3371
 
3372
+ ########################################
3373
+ # ../../../omlish/subprocesses/run.py
3374
+
3375
+
3376
+ ##
3377
+
3378
+
3379
+ @dc.dataclass(frozen=True)
3380
+ class SubprocessRunOutput(ta.Generic[T]):
3381
+ proc: T
3382
+
3383
+ returncode: int # noqa
3384
+
3385
+ stdout: ta.Optional[bytes] = None
3386
+ stderr: ta.Optional[bytes] = None
3387
+
3388
+
3389
+ ##
3390
+
3391
+
3392
+ @dc.dataclass(frozen=True)
3393
+ class SubprocessRun:
3394
+ cmd: ta.Sequence[str]
3395
+ input: ta.Any = None
3396
+ timeout: ta.Optional[float] = None
3397
+ check: bool = False
3398
+ capture_output: ta.Optional[bool] = None
3399
+ kwargs: ta.Optional[ta.Mapping[str, ta.Any]] = None
3400
+
3401
+ @classmethod
3402
+ def of(
3403
+ cls,
3404
+ *cmd: str,
3405
+ input: ta.Any = None, # noqa
3406
+ timeout: ta.Optional[float] = None,
3407
+ check: bool = False, # noqa
3408
+ capture_output: ta.Optional[bool] = None,
3409
+ **kwargs: ta.Any,
3410
+ ) -> 'SubprocessRun':
3411
+ return cls(
3412
+ cmd=cmd,
3413
+ input=input,
3414
+ timeout=timeout,
3415
+ check=check,
3416
+ capture_output=capture_output,
3417
+ kwargs=kwargs,
3418
+ )
3419
+
3420
+ #
3421
+
3422
+ _DEFAULT_SUBPROCESSES: ta.ClassVar[ta.Optional[ta.Any]] = None # AbstractSubprocesses
3423
+
3424
+ def run(
3425
+ self,
3426
+ subprocesses: ta.Optional[ta.Any] = None, # AbstractSubprocesses
3427
+ ) -> SubprocessRunOutput:
3428
+ if subprocesses is None:
3429
+ subprocesses = self._DEFAULT_SUBPROCESSES
3430
+ return check.not_none(subprocesses).run_(self) # type: ignore[attr-defined]
3431
+
3432
+ _DEFAULT_ASYNC_SUBPROCESSES: ta.ClassVar[ta.Optional[ta.Any]] = None # AbstractAsyncSubprocesses
3433
+
3434
+ async def async_run(
3435
+ self,
3436
+ async_subprocesses: ta.Optional[ta.Any] = None, # AbstractAsyncSubprocesses
3437
+ ) -> SubprocessRunOutput:
3438
+ if async_subprocesses is None:
3439
+ async_subprocesses = self._DEFAULT_ASYNC_SUBPROCESSES
3440
+ return await check.not_none(async_subprocesses).run_(self) # type: ignore[attr-defined]
3441
+
3442
+
3443
+ ##
3444
+
3445
+
3446
+ class SubprocessRunnable(abc.ABC, ta.Generic[T]):
3447
+ @abc.abstractmethod
3448
+ def make_run(self) -> SubprocessRun:
3449
+ raise NotImplementedError
3450
+
3451
+ @abc.abstractmethod
3452
+ def handle_run_output(self, output: SubprocessRunOutput) -> T:
3453
+ raise NotImplementedError
3454
+
3455
+ #
3456
+
3457
+ def run(self, subprocesses: ta.Optional[ta.Any] = None) -> T: # AbstractSubprocesses
3458
+ return self.handle_run_output(self.make_run().run(subprocesses))
3459
+
3460
+ async def async_run(self, async_subprocesses: ta.Optional[ta.Any] = None) -> T: # AbstractAsyncSubprocesses
3461
+ return self.handle_run_output(await self.make_run().async_run(async_subprocesses))
3462
+
3463
+
3372
3464
  ########################################
3373
3465
  # ../types.py
3374
3466
 
@@ -3607,23 +3699,7 @@ def configure_standard_logging(
3607
3699
 
3608
3700
 
3609
3701
  ########################################
3610
- # ../../../omlish/subprocesses.py
3611
-
3612
-
3613
- ##
3614
-
3615
-
3616
- # Valid channel type kwarg values:
3617
- # - A special flag negative int
3618
- # - A positive fd int
3619
- # - A file-like object
3620
- # - None
3621
-
3622
- SUBPROCESS_CHANNEL_OPTION_VALUES: ta.Mapping[SubprocessChannelOption, int] = {
3623
- 'pipe': subprocess.PIPE,
3624
- 'stdout': subprocess.STDOUT,
3625
- 'devnull': subprocess.DEVNULL,
3626
- }
3702
+ # ../../../omlish/subprocesses/wrap.py
3627
3703
 
3628
3704
 
3629
3705
  ##
@@ -3643,22 +3719,68 @@ def subprocess_maybe_shell_wrap_exec(*cmd: str) -> ta.Tuple[str, ...]:
3643
3719
  return cmd
3644
3720
 
3645
3721
 
3722
+ ########################################
3723
+ # ../providers/base.py
3724
+ """
3725
+ TODO:
3726
+ - backends
3727
+ - local builds
3728
+ - deadsnakes?
3729
+ - uv
3730
+ - loose versions
3731
+ """
3732
+
3733
+
3646
3734
  ##
3647
3735
 
3648
3736
 
3649
- def subprocess_close(
3650
- proc: subprocess.Popen,
3651
- timeout: ta.Optional[float] = None,
3652
- ) -> None:
3653
- # TODO: terminate, sleep, kill
3654
- if proc.stdout:
3655
- proc.stdout.close()
3656
- if proc.stderr:
3657
- proc.stderr.close()
3658
- if proc.stdin:
3659
- proc.stdin.close()
3737
+ class InterpProvider(abc.ABC):
3738
+ name: ta.ClassVar[str]
3660
3739
 
3661
- proc.wait(timeout)
3740
+ def __init_subclass__(cls, **kwargs: ta.Any) -> None:
3741
+ super().__init_subclass__(**kwargs)
3742
+ if abc.ABC not in cls.__bases__ and 'name' not in cls.__dict__:
3743
+ sfx = 'InterpProvider'
3744
+ if not cls.__name__.endswith(sfx):
3745
+ raise NameError(cls)
3746
+ setattr(cls, 'name', snake_case(cls.__name__[:-len(sfx)]))
3747
+
3748
+ @abc.abstractmethod
3749
+ def get_installed_versions(self, spec: InterpSpecifier) -> ta.Awaitable[ta.Sequence[InterpVersion]]:
3750
+ raise NotImplementedError
3751
+
3752
+ @abc.abstractmethod
3753
+ def get_installed_version(self, version: InterpVersion) -> ta.Awaitable[Interp]:
3754
+ raise NotImplementedError
3755
+
3756
+ async def get_installable_versions(self, spec: InterpSpecifier) -> ta.Sequence[InterpVersion]:
3757
+ return []
3758
+
3759
+ async def install_version(self, version: InterpVersion) -> Interp:
3760
+ raise TypeError
3761
+
3762
+
3763
+ InterpProviders = ta.NewType('InterpProviders', ta.Sequence[InterpProvider])
3764
+
3765
+
3766
+ ########################################
3767
+ # ../../../omlish/subprocesses/base.py
3768
+
3769
+
3770
+ ##
3771
+
3772
+
3773
+ # Valid channel type kwarg values:
3774
+ # - A special flag negative int
3775
+ # - A positive fd int
3776
+ # - A file-like object
3777
+ # - None
3778
+
3779
+ SUBPROCESS_CHANNEL_OPTION_VALUES: ta.Mapping[SubprocessChannelOption, int] = {
3780
+ 'pipe': subprocess.PIPE,
3781
+ 'stdout': subprocess.STDOUT,
3782
+ 'devnull': subprocess.DEVNULL,
3783
+ }
3662
3784
 
3663
3785
 
3664
3786
  ##
@@ -3845,174 +3967,96 @@ class BaseSubprocesses(abc.ABC): # noqa
3845
3967
  return e
3846
3968
 
3847
3969
 
3848
- ##
3849
-
3850
-
3851
- @dc.dataclass(frozen=True)
3852
- class SubprocessRun:
3853
- cmd: ta.Sequence[str]
3854
- input: ta.Any = None
3855
- timeout: ta.Optional[float] = None
3856
- check: bool = False
3857
- capture_output: ta.Optional[bool] = None
3858
- kwargs: ta.Optional[ta.Mapping[str, ta.Any]] = None
3859
-
3860
- @classmethod
3861
- def of(
3862
- cls,
3863
- *cmd: str,
3864
- input: ta.Any = None, # noqa
3865
- timeout: ta.Optional[float] = None,
3866
- check: bool = False,
3867
- capture_output: ta.Optional[bool] = None,
3868
- **kwargs: ta.Any,
3869
- ) -> 'SubprocessRun':
3870
- return cls(
3871
- cmd=cmd,
3872
- input=input,
3873
- timeout=timeout,
3874
- check=check,
3875
- capture_output=capture_output,
3876
- kwargs=kwargs,
3877
- )
3970
+ ########################################
3971
+ # ../resolvers.py
3878
3972
 
3879
3973
 
3880
3974
  @dc.dataclass(frozen=True)
3881
- class SubprocessRunOutput(ta.Generic[T]):
3882
- proc: T
3883
-
3884
- returncode: int # noqa
3885
-
3886
- stdout: ta.Optional[bytes] = None
3887
- stderr: ta.Optional[bytes] = None
3888
-
3889
-
3890
- class AbstractSubprocesses(BaseSubprocesses, abc.ABC):
3891
- @abc.abstractmethod
3892
- def run_(self, run: SubprocessRun) -> SubprocessRunOutput:
3893
- raise NotImplementedError
3894
-
3895
- def run(
3896
- self,
3897
- *cmd: str,
3898
- input: ta.Any = None, # noqa
3899
- timeout: ta.Optional[float] = None,
3900
- check: bool = False,
3901
- capture_output: ta.Optional[bool] = None,
3902
- **kwargs: ta.Any,
3903
- ) -> SubprocessRunOutput:
3904
- return self.run_(SubprocessRun(
3905
- cmd=cmd,
3906
- input=input,
3907
- timeout=timeout,
3908
- check=check,
3909
- capture_output=capture_output,
3910
- kwargs=kwargs,
3911
- ))
3975
+ class InterpResolverProviders:
3976
+ providers: ta.Sequence[ta.Tuple[str, InterpProvider]]
3912
3977
 
3913
- #
3914
3978
 
3915
- @abc.abstractmethod
3916
- def check_call(
3979
+ class InterpResolver:
3980
+ def __init__(
3917
3981
  self,
3918
- *cmd: str,
3919
- stdout: ta.Any = sys.stderr,
3920
- **kwargs: ta.Any,
3982
+ providers: InterpResolverProviders,
3921
3983
  ) -> None:
3922
- raise NotImplementedError
3923
-
3924
- @abc.abstractmethod
3925
- def check_output(
3926
- self,
3927
- *cmd: str,
3928
- **kwargs: ta.Any,
3929
- ) -> bytes:
3930
- raise NotImplementedError
3984
+ super().__init__()
3931
3985
 
3932
- #
3986
+ self._providers: ta.Mapping[str, InterpProvider] = collections.OrderedDict(providers.providers)
3933
3987
 
3934
- def check_output_str(
3935
- self,
3936
- *cmd: str,
3937
- **kwargs: ta.Any,
3938
- ) -> str:
3939
- return self.check_output(*cmd, **kwargs).decode().strip()
3988
+ async def _resolve_installed(self, spec: InterpSpecifier) -> ta.Optional[ta.Tuple[InterpProvider, InterpVersion]]:
3989
+ lst = [
3990
+ (i, si)
3991
+ for i, p in enumerate(self._providers.values())
3992
+ for si in await p.get_installed_versions(spec)
3993
+ if spec.contains(si)
3994
+ ]
3940
3995
 
3941
- #
3996
+ slst = sorted(lst, key=lambda t: (-t[0], t[1].version))
3997
+ if not slst:
3998
+ return None
3942
3999
 
3943
- def try_call(
3944
- self,
3945
- *cmd: str,
3946
- **kwargs: ta.Any,
3947
- ) -> bool:
3948
- if isinstance(self.try_fn(self.check_call, *cmd, **kwargs), Exception):
3949
- return False
3950
- else:
3951
- return True
4000
+ bi, bv = slst[-1]
4001
+ bp = list(self._providers.values())[bi]
4002
+ return (bp, bv)
3952
4003
 
3953
- def try_output(
4004
+ async def resolve(
3954
4005
  self,
3955
- *cmd: str,
3956
- **kwargs: ta.Any,
3957
- ) -> ta.Optional[bytes]:
3958
- if isinstance(ret := self.try_fn(self.check_output, *cmd, **kwargs), Exception):
3959
- return None
3960
- else:
3961
- return ret
4006
+ spec: InterpSpecifier,
4007
+ *,
4008
+ install: bool = False,
4009
+ ) -> ta.Optional[Interp]:
4010
+ tup = await self._resolve_installed(spec)
4011
+ if tup is not None:
4012
+ bp, bv = tup
4013
+ return await bp.get_installed_version(bv)
3962
4014
 
3963
- def try_output_str(
3964
- self,
3965
- *cmd: str,
3966
- **kwargs: ta.Any,
3967
- ) -> ta.Optional[str]:
3968
- if (ret := self.try_output(*cmd, **kwargs)) is None:
4015
+ if not install:
3969
4016
  return None
3970
- else:
3971
- return ret.decode().strip()
3972
-
3973
-
3974
- ##
3975
4017
 
4018
+ tp = list(self._providers.values())[0] # noqa
3976
4019
 
3977
- class Subprocesses(AbstractSubprocesses):
3978
- def run_(self, run: SubprocessRun) -> SubprocessRunOutput[subprocess.CompletedProcess]:
3979
- proc = subprocess.run(
3980
- run.cmd,
3981
- input=run.input,
3982
- timeout=run.timeout,
3983
- check=run.check,
3984
- capture_output=run.capture_output or False,
3985
- **(run.kwargs or {}),
4020
+ sv = sorted(
4021
+ [s for s in await tp.get_installable_versions(spec) if s in spec],
4022
+ key=lambda s: s.version,
3986
4023
  )
4024
+ if not sv:
4025
+ return None
3987
4026
 
3988
- return SubprocessRunOutput(
3989
- proc=proc,
3990
-
3991
- returncode=proc.returncode,
4027
+ bv = sv[-1]
4028
+ return await tp.install_version(bv)
3992
4029
 
3993
- stdout=proc.stdout, # noqa
3994
- stderr=proc.stderr, # noqa
3995
- )
4030
+ async def list(self, spec: InterpSpecifier) -> None:
4031
+ print('installed:')
4032
+ for n, p in self._providers.items():
4033
+ lst = [
4034
+ si
4035
+ for si in await p.get_installed_versions(spec)
4036
+ if spec.contains(si)
4037
+ ]
4038
+ if lst:
4039
+ print(f' {n}')
4040
+ for si in lst:
4041
+ print(f' {si}')
3996
4042
 
3997
- def check_call(
3998
- self,
3999
- *cmd: str,
4000
- stdout: ta.Any = sys.stderr,
4001
- **kwargs: ta.Any,
4002
- ) -> None:
4003
- with self.prepare_and_wrap(*cmd, stdout=stdout, **kwargs) as (cmd, kwargs): # noqa
4004
- subprocess.check_call(cmd, **kwargs)
4043
+ print()
4005
4044
 
4006
- def check_output(
4007
- self,
4008
- *cmd: str,
4009
- **kwargs: ta.Any,
4010
- ) -> bytes:
4011
- with self.prepare_and_wrap(*cmd, **kwargs) as (cmd, kwargs): # noqa
4012
- return subprocess.check_output(cmd, **kwargs)
4045
+ print('installable:')
4046
+ for n, p in self._providers.items():
4047
+ lst = [
4048
+ si
4049
+ for si in await p.get_installable_versions(spec)
4050
+ if spec.contains(si)
4051
+ ]
4052
+ if lst:
4053
+ print(f' {n}')
4054
+ for si in lst:
4055
+ print(f' {si}')
4013
4056
 
4014
4057
 
4015
- subprocesses = Subprocesses()
4058
+ ########################################
4059
+ # ../../../omlish/subprocesses/async_.py
4016
4060
 
4017
4061
 
4018
4062
  ##
@@ -4102,50 +4146,6 @@ class AbstractAsyncSubprocesses(BaseSubprocesses):
4102
4146
  return ret.decode().strip()
4103
4147
 
4104
4148
 
4105
- ########################################
4106
- # ../providers/base.py
4107
- """
4108
- TODO:
4109
- - backends
4110
- - local builds
4111
- - deadsnakes?
4112
- - uv
4113
- - loose versions
4114
- """
4115
-
4116
-
4117
- ##
4118
-
4119
-
4120
- class InterpProvider(abc.ABC):
4121
- name: ta.ClassVar[str]
4122
-
4123
- def __init_subclass__(cls, **kwargs: ta.Any) -> None:
4124
- super().__init_subclass__(**kwargs)
4125
- if abc.ABC not in cls.__bases__ and 'name' not in cls.__dict__:
4126
- sfx = 'InterpProvider'
4127
- if not cls.__name__.endswith(sfx):
4128
- raise NameError(cls)
4129
- setattr(cls, 'name', snake_case(cls.__name__[:-len(sfx)]))
4130
-
4131
- @abc.abstractmethod
4132
- def get_installed_versions(self, spec: InterpSpecifier) -> ta.Awaitable[ta.Sequence[InterpVersion]]:
4133
- raise NotImplementedError
4134
-
4135
- @abc.abstractmethod
4136
- def get_installed_version(self, version: InterpVersion) -> ta.Awaitable[Interp]:
4137
- raise NotImplementedError
4138
-
4139
- async def get_installable_versions(self, spec: InterpSpecifier) -> ta.Sequence[InterpVersion]:
4140
- return []
4141
-
4142
- async def install_version(self, version: InterpVersion) -> Interp:
4143
- raise TypeError
4144
-
4145
-
4146
- InterpProviders = ta.NewType('InterpProviders', ta.Sequence[InterpProvider])
4147
-
4148
-
4149
4149
  ########################################
4150
4150
  # ../../../omlish/asyncs/asyncio/subprocesses.py
4151
4151
 
@@ -4288,19 +4288,19 @@ class AsyncioSubprocesses(AbstractAsyncSubprocesses):
4288
4288
  timeout: ta.Optional[float] = None,
4289
4289
  **kwargs: ta.Any,
4290
4290
  ) -> ta.AsyncGenerator[asyncio.subprocess.Process, None]:
4291
- fac: ta.Any
4292
- if shell:
4293
- fac = functools.partial(
4294
- asyncio.create_subprocess_shell,
4295
- check.single(cmd),
4296
- )
4297
- else:
4298
- fac = functools.partial(
4299
- asyncio.create_subprocess_exec,
4300
- *cmd,
4301
- )
4302
-
4303
4291
  with self.prepare_and_wrap( *cmd, shell=shell, **kwargs) as (cmd, kwargs): # noqa
4292
+ fac: ta.Any
4293
+ if shell:
4294
+ fac = functools.partial(
4295
+ asyncio.create_subprocess_shell,
4296
+ check.single(cmd),
4297
+ )
4298
+ else:
4299
+ fac = functools.partial(
4300
+ asyncio.create_subprocess_exec,
4301
+ *cmd,
4302
+ )
4303
+
4304
4304
  proc: asyncio.subprocess.Process = await fac(**kwargs)
4305
4305
  try:
4306
4306
  yield proc
@@ -4541,94 +4541,6 @@ class Pyenv:
4541
4541
  return True
4542
4542
 
4543
4543
 
4544
- ########################################
4545
- # ../resolvers.py
4546
-
4547
-
4548
- @dc.dataclass(frozen=True)
4549
- class InterpResolverProviders:
4550
- providers: ta.Sequence[ta.Tuple[str, InterpProvider]]
4551
-
4552
-
4553
- class InterpResolver:
4554
- def __init__(
4555
- self,
4556
- providers: InterpResolverProviders,
4557
- ) -> None:
4558
- super().__init__()
4559
-
4560
- self._providers: ta.Mapping[str, InterpProvider] = collections.OrderedDict(providers.providers)
4561
-
4562
- async def _resolve_installed(self, spec: InterpSpecifier) -> ta.Optional[ta.Tuple[InterpProvider, InterpVersion]]:
4563
- lst = [
4564
- (i, si)
4565
- for i, p in enumerate(self._providers.values())
4566
- for si in await p.get_installed_versions(spec)
4567
- if spec.contains(si)
4568
- ]
4569
-
4570
- slst = sorted(lst, key=lambda t: (-t[0], t[1].version))
4571
- if not slst:
4572
- return None
4573
-
4574
- bi, bv = slst[-1]
4575
- bp = list(self._providers.values())[bi]
4576
- return (bp, bv)
4577
-
4578
- async def resolve(
4579
- self,
4580
- spec: InterpSpecifier,
4581
- *,
4582
- install: bool = False,
4583
- ) -> ta.Optional[Interp]:
4584
- tup = await self._resolve_installed(spec)
4585
- if tup is not None:
4586
- bp, bv = tup
4587
- return await bp.get_installed_version(bv)
4588
-
4589
- if not install:
4590
- return None
4591
-
4592
- tp = list(self._providers.values())[0] # noqa
4593
-
4594
- sv = sorted(
4595
- [s for s in await tp.get_installable_versions(spec) if s in spec],
4596
- key=lambda s: s.version,
4597
- )
4598
- if not sv:
4599
- return None
4600
-
4601
- bv = sv[-1]
4602
- return await tp.install_version(bv)
4603
-
4604
- async def list(self, spec: InterpSpecifier) -> None:
4605
- print('installed:')
4606
- for n, p in self._providers.items():
4607
- lst = [
4608
- si
4609
- for si in await p.get_installed_versions(spec)
4610
- if spec.contains(si)
4611
- ]
4612
- if lst:
4613
- print(f' {n}')
4614
- for si in lst:
4615
- print(f' {si}')
4616
-
4617
- print()
4618
-
4619
- print('installable:')
4620
- for n, p in self._providers.items():
4621
- lst = [
4622
- si
4623
- for si in await p.get_installable_versions(spec)
4624
- if spec.contains(si)
4625
- ]
4626
- if lst:
4627
- print(f' {n}')
4628
- for si in lst:
4629
- print(f' {si}')
4630
-
4631
-
4632
4544
  ########################################
4633
4545
  # ../providers/running.py
4634
4546