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.
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