omdev 0.0.0.dev148__py3-none-any.whl → 0.0.0.dev150__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.

Potentially problematic release.


This version of omdev might be problematic. Click here for more details.

omdev/scripts/interp.py CHANGED
@@ -64,6 +64,11 @@ CallableT = ta.TypeVar('CallableT', bound=ta.Callable)
64
64
 
65
65
  # ../../omlish/lite/check.py
66
66
  SizedT = ta.TypeVar('SizedT', bound=ta.Sized)
67
+ CheckMessage = ta.Union[str, ta.Callable[..., ta.Optional[str]], None] # ta.TypeAlias
68
+ CheckLateConfigureFn = ta.Callable[['Checks'], None]
69
+ CheckOnRaiseFn = ta.Callable[[Exception], None] # ta.TypeAlias
70
+ CheckExceptionFactory = ta.Callable[..., Exception] # ta.TypeAlias
71
+ CheckArgsRenderer = ta.Callable[..., ta.Optional[str]] # ta.TypeAlias
67
72
 
68
73
  # ../packaging/specifiers.py
69
74
  UnparsedVersion = ta.Union['Version', str]
@@ -599,99 +604,454 @@ def async_cached_nullary(fn): # ta.Callable[..., T]) -> ta.Callable[..., T]:
599
604
 
600
605
  ########################################
601
606
  # ../../../omlish/lite/check.py
607
+ """
608
+ TODO:
609
+ - def maybe(v: lang.Maybe[T])
610
+ - patch / override lite.check ?
611
+ - checker interface?
612
+ """
613
+
614
+
615
+ ##
616
+
617
+
618
+ class Checks:
619
+ def __init__(self) -> None:
620
+ super().__init__()
621
+
622
+ self._config_lock = threading.RLock()
623
+ self._on_raise_fns: ta.Sequence[CheckOnRaiseFn] = []
624
+ self._exception_factory: CheckExceptionFactory = Checks.default_exception_factory
625
+ self._args_renderer: ta.Optional[CheckArgsRenderer] = None
626
+ self._late_configure_fns: ta.Sequence[CheckLateConfigureFn] = []
627
+
628
+ @staticmethod
629
+ def default_exception_factory(exc_cls: ta.Type[Exception], *args, **kwargs) -> Exception:
630
+ return exc_cls(*args, **kwargs) # noqa
631
+
632
+ #
633
+
634
+ def register_on_raise(self, fn: CheckOnRaiseFn) -> None:
635
+ with self._config_lock:
636
+ self._on_raise_fns = [*self._on_raise_fns, fn]
637
+
638
+ def unregister_on_raise(self, fn: CheckOnRaiseFn) -> None:
639
+ with self._config_lock:
640
+ self._on_raise_fns = [e for e in self._on_raise_fns if e != fn]
641
+
642
+ #
643
+
644
+ def set_exception_factory(self, factory: CheckExceptionFactory) -> None:
645
+ self._exception_factory = factory
646
+
647
+ def set_args_renderer(self, renderer: ta.Optional[CheckArgsRenderer]) -> None:
648
+ self._args_renderer = renderer
649
+
650
+ #
651
+
652
+ def register_late_configure(self, fn: CheckLateConfigureFn) -> None:
653
+ with self._config_lock:
654
+ self._late_configure_fns = [*self._late_configure_fns, fn]
655
+
656
+ def _late_configure(self) -> None:
657
+ if not self._late_configure_fns:
658
+ return
659
+
660
+ with self._config_lock:
661
+ if not (lc := self._late_configure_fns):
662
+ return
663
+
664
+ for fn in lc:
665
+ fn(self)
666
+
667
+ self._late_configure_fns = []
668
+
669
+ #
670
+
671
+ class _ArgsKwargs:
672
+ def __init__(self, *args, **kwargs):
673
+ self.args = args
674
+ self.kwargs = kwargs
675
+
676
+ def _raise(
677
+ self,
678
+ exception_type: ta.Type[Exception],
679
+ default_message: str,
680
+ message: CheckMessage,
681
+ ak: _ArgsKwargs = _ArgsKwargs(),
682
+ *,
683
+ render_fmt: ta.Optional[str] = None,
684
+ ) -> ta.NoReturn:
685
+ exc_args = ()
686
+ if callable(message):
687
+ message = ta.cast(ta.Callable, message)(*ak.args, **ak.kwargs)
688
+ if isinstance(message, tuple):
689
+ message, *exc_args = message # type: ignore
690
+
691
+ if message is None:
692
+ message = default_message
693
+
694
+ self._late_configure()
695
+
696
+ if render_fmt is not None and (af := self._args_renderer) is not None:
697
+ rendered_args = af(render_fmt, *ak.args)
698
+ if rendered_args is not None:
699
+ message = f'{message} : {rendered_args}'
700
+
701
+ exc = self._exception_factory(
702
+ exception_type,
703
+ message,
704
+ *exc_args,
705
+ *ak.args,
706
+ **ak.kwargs,
707
+ )
708
+
709
+ for fn in self._on_raise_fns:
710
+ fn(exc)
711
+
712
+ raise exc
713
+
714
+ #
715
+
716
+ def _unpack_isinstance_spec(self, spec: ta.Any) -> tuple:
717
+ if isinstance(spec, type):
718
+ return (spec,)
719
+ if not isinstance(spec, tuple):
720
+ spec = (spec,)
721
+ if None in spec:
722
+ spec = tuple(filter(None, spec)) + (None.__class__,) # noqa
723
+ if ta.Any in spec:
724
+ spec = (object,)
725
+ return spec
726
+
727
+ def isinstance(self, v: ta.Any, spec: ta.Union[ta.Type[T], tuple], msg: CheckMessage = None) -> T: # noqa
728
+ if not isinstance(v, self._unpack_isinstance_spec(spec)):
729
+ self._raise(
730
+ TypeError,
731
+ 'Must be instance',
732
+ msg,
733
+ Checks._ArgsKwargs(v, spec),
734
+ render_fmt='not isinstance(%s, %s)',
735
+ )
736
+
737
+ return v
738
+
739
+ def of_isinstance(self, spec: ta.Union[ta.Type[T], tuple], msg: CheckMessage = None) -> ta.Callable[[ta.Any], T]:
740
+ def inner(v):
741
+ return self.isinstance(v, self._unpack_isinstance_spec(spec), msg)
742
+
743
+ return inner
744
+
745
+ def cast(self, v: ta.Any, cls: ta.Type[T], msg: CheckMessage = None) -> T: # noqa
746
+ if not isinstance(v, cls):
747
+ self._raise(
748
+ TypeError,
749
+ 'Must be instance',
750
+ msg,
751
+ Checks._ArgsKwargs(v, cls),
752
+ )
753
+
754
+ return v
755
+
756
+ def of_cast(self, cls: ta.Type[T], msg: CheckMessage = None) -> ta.Callable[[T], T]:
757
+ def inner(v):
758
+ return self.cast(v, cls, msg)
759
+
760
+ return inner
761
+
762
+ def not_isinstance(self, v: T, spec: ta.Any, msg: CheckMessage = None) -> T: # noqa
763
+ if isinstance(v, self._unpack_isinstance_spec(spec)):
764
+ self._raise(
765
+ TypeError,
766
+ 'Must not be instance',
767
+ msg,
768
+ Checks._ArgsKwargs(v, spec),
769
+ render_fmt='isinstance(%s, %s)',
770
+ )
771
+
772
+ return v
773
+
774
+ def of_not_isinstance(self, spec: ta.Any, msg: CheckMessage = None) -> ta.Callable[[T], T]:
775
+ def inner(v):
776
+ return self.not_isinstance(v, self._unpack_isinstance_spec(spec), msg)
777
+
778
+ return inner
779
+
780
+ ##
781
+
782
+ def issubclass(self, v: ta.Type[T], spec: ta.Any, msg: CheckMessage = None) -> ta.Type[T]: # noqa
783
+ if not issubclass(v, spec):
784
+ self._raise(
785
+ TypeError,
786
+ 'Must be subclass',
787
+ msg,
788
+ Checks._ArgsKwargs(v, spec),
789
+ render_fmt='not issubclass(%s, %s)',
790
+ )
791
+
792
+ return v
793
+
794
+ def not_issubclass(self, v: ta.Type[T], spec: ta.Any, msg: CheckMessage = None) -> ta.Type[T]: # noqa
795
+ if issubclass(v, spec):
796
+ self._raise(
797
+ TypeError,
798
+ 'Must not be subclass',
799
+ msg,
800
+ Checks._ArgsKwargs(v, spec),
801
+ render_fmt='issubclass(%s, %s)',
802
+ )
803
+
804
+ return v
805
+
806
+ #
807
+
808
+ def in_(self, v: T, c: ta.Container[T], msg: CheckMessage = None) -> T:
809
+ if v not in c:
810
+ self._raise(
811
+ ValueError,
812
+ 'Must be in',
813
+ msg,
814
+ Checks._ArgsKwargs(v, c),
815
+ render_fmt='%s not in %s',
816
+ )
817
+
818
+ return v
819
+
820
+ def not_in(self, v: T, c: ta.Container[T], msg: CheckMessage = None) -> T:
821
+ if v in c:
822
+ self._raise(
823
+ ValueError,
824
+ 'Must not be in',
825
+ msg,
826
+ Checks._ArgsKwargs(v, c),
827
+ render_fmt='%s in %s',
828
+ )
829
+
830
+ return v
831
+
832
+ def empty(self, v: SizedT, msg: CheckMessage = None) -> SizedT:
833
+ if len(v) != 0:
834
+ self._raise(
835
+ ValueError,
836
+ 'Must be empty',
837
+ msg,
838
+ Checks._ArgsKwargs(v),
839
+ render_fmt='%s',
840
+ )
841
+
842
+ return v
843
+
844
+ def iterempty(self, v: ta.Iterable[T], msg: CheckMessage = None) -> ta.Iterable[T]:
845
+ it = iter(v)
846
+ try:
847
+ next(it)
848
+ except StopIteration:
849
+ pass
850
+ else:
851
+ self._raise(
852
+ ValueError,
853
+ 'Must be empty',
854
+ msg,
855
+ Checks._ArgsKwargs(v),
856
+ render_fmt='%s',
857
+ )
602
858
 
859
+ return v
603
860
 
604
- def check_isinstance(v: ta.Any, spec: ta.Union[ta.Type[T], tuple]) -> T:
605
- if not isinstance(v, spec):
606
- raise TypeError(v)
607
- return v
861
+ def not_empty(self, v: SizedT, msg: CheckMessage = None) -> SizedT:
862
+ if len(v) == 0:
863
+ self._raise(
864
+ ValueError,
865
+ 'Must not be empty',
866
+ msg,
867
+ Checks._ArgsKwargs(v),
868
+ render_fmt='%s',
869
+ )
608
870
 
871
+ return v
609
872
 
610
- def check_not_isinstance(v: T, spec: ta.Union[type, tuple]) -> T:
611
- if isinstance(v, spec):
612
- raise TypeError(v)
613
- return v
873
+ def unique(self, it: ta.Iterable[T], msg: CheckMessage = None) -> ta.Iterable[T]:
874
+ dupes = [e for e, c in collections.Counter(it).items() if c > 1]
875
+ if dupes:
876
+ self._raise(
877
+ ValueError,
878
+ 'Must be unique',
879
+ msg,
880
+ Checks._ArgsKwargs(it, dupes),
881
+ )
614
882
 
883
+ return it
615
884
 
616
- def check_none(v: T) -> None:
617
- if v is not None:
618
- raise ValueError(v)
885
+ def single(self, obj: ta.Iterable[T], message: CheckMessage = None) -> T:
886
+ try:
887
+ [value] = obj
888
+ except ValueError:
889
+ self._raise(
890
+ ValueError,
891
+ 'Must be single',
892
+ message,
893
+ Checks._ArgsKwargs(obj),
894
+ render_fmt='%s',
895
+ )
619
896
 
897
+ return value
620
898
 
621
- def check_not_none(v: ta.Optional[T]) -> T:
622
- if v is None:
623
- raise ValueError
624
- return v
899
+ def opt_single(self, obj: ta.Iterable[T], message: CheckMessage = None) -> ta.Optional[T]:
900
+ it = iter(obj)
901
+ try:
902
+ value = next(it)
903
+ except StopIteration:
904
+ return None
625
905
 
906
+ try:
907
+ next(it)
908
+ except StopIteration:
909
+ return value # noqa
910
+
911
+ self._raise(
912
+ ValueError,
913
+ 'Must be empty or single',
914
+ message,
915
+ Checks._ArgsKwargs(obj),
916
+ render_fmt='%s',
917
+ )
626
918
 
627
- def check_not(v: ta.Any) -> None:
628
- if v:
629
- raise ValueError(v)
630
- return v
919
+ raise RuntimeError # noqa
631
920
 
921
+ #
632
922
 
633
- def check_non_empty_str(v: ta.Optional[str]) -> str:
634
- if not v:
635
- raise ValueError
636
- return v
923
+ def none(self, v: ta.Any, msg: CheckMessage = None) -> None:
924
+ if v is not None:
925
+ self._raise(
926
+ ValueError,
927
+ 'Must be None',
928
+ msg,
929
+ Checks._ArgsKwargs(v),
930
+ render_fmt='%s',
931
+ )
637
932
 
933
+ def not_none(self, v: ta.Optional[T], msg: CheckMessage = None) -> T:
934
+ if v is None:
935
+ self._raise(
936
+ ValueError,
937
+ 'Must not be None',
938
+ msg,
939
+ Checks._ArgsKwargs(v),
940
+ render_fmt='%s',
941
+ )
638
942
 
639
- def check_state(v: bool, msg: str = 'Illegal state') -> None:
640
- if not v:
641
- raise ValueError(msg)
943
+ return v
642
944
 
945
+ #
643
946
 
644
- def check_equal(l: T, r: T) -> T:
645
- if l != r:
646
- raise ValueError(l, r)
647
- return l
947
+ def equal(self, v: T, o: ta.Any, msg: CheckMessage = None) -> T:
948
+ if o != v:
949
+ self._raise(
950
+ ValueError,
951
+ 'Must be equal',
952
+ msg,
953
+ Checks._ArgsKwargs(v, o),
954
+ render_fmt='%s != %s',
955
+ )
956
+
957
+ return v
958
+
959
+ def is_(self, v: T, o: ta.Any, msg: CheckMessage = None) -> T:
960
+ if o is not v:
961
+ self._raise(
962
+ ValueError,
963
+ 'Must be the same',
964
+ msg,
965
+ Checks._ArgsKwargs(v, o),
966
+ render_fmt='%s is not %s',
967
+ )
648
968
 
969
+ return v
649
970
 
650
- def check_not_equal(l: T, r: T) -> T:
651
- if l == r:
652
- raise ValueError(l, r)
653
- return l
971
+ def is_not(self, v: T, o: ta.Any, msg: CheckMessage = None) -> T:
972
+ if o is v:
973
+ self._raise(
974
+ ValueError,
975
+ 'Must not be the same',
976
+ msg,
977
+ Checks._ArgsKwargs(v, o),
978
+ render_fmt='%s is %s',
979
+ )
654
980
 
981
+ return v
655
982
 
656
- def check_is(l: T, r: T) -> T:
657
- if l is not r:
658
- raise ValueError(l, r)
659
- return l
983
+ def callable(self, v: T, msg: CheckMessage = None) -> T: # noqa
984
+ if not callable(v):
985
+ self._raise(
986
+ TypeError,
987
+ 'Must be callable',
988
+ msg,
989
+ Checks._ArgsKwargs(v),
990
+ render_fmt='%s',
991
+ )
660
992
 
993
+ return v # type: ignore
661
994
 
662
- def check_is_not(l: T, r: ta.Any) -> T:
663
- if l is r:
664
- raise ValueError(l, r)
665
- return l
995
+ def non_empty_str(self, v: ta.Optional[str], msg: CheckMessage = None) -> str:
996
+ if not isinstance(v, str) or not v:
997
+ self._raise(
998
+ ValueError,
999
+ 'Must be non-empty str',
1000
+ msg,
1001
+ Checks._ArgsKwargs(v),
1002
+ render_fmt='%s',
1003
+ )
666
1004
 
1005
+ return v
667
1006
 
668
- def check_in(v: T, c: ta.Container[T]) -> T:
669
- if v not in c:
670
- raise ValueError(v, c)
671
- return v
1007
+ def replacing(self, expected: ta.Any, old: ta.Any, new: T, msg: CheckMessage = None) -> T:
1008
+ if old != expected:
1009
+ self._raise(
1010
+ ValueError,
1011
+ 'Must be replacing',
1012
+ msg,
1013
+ Checks._ArgsKwargs(expected, old, new),
1014
+ render_fmt='%s -> %s -> %s',
1015
+ )
672
1016
 
1017
+ return new
673
1018
 
674
- def check_not_in(v: T, c: ta.Container[T]) -> T:
675
- if v in c:
676
- raise ValueError(v, c)
677
- return v
1019
+ def replacing_none(self, old: ta.Any, new: T, msg: CheckMessage = None) -> T:
1020
+ if old is not None:
1021
+ self._raise(
1022
+ ValueError,
1023
+ 'Must be replacing None',
1024
+ msg,
1025
+ Checks._ArgsKwargs(old, new),
1026
+ render_fmt='%s -> %s',
1027
+ )
678
1028
 
1029
+ return new
679
1030
 
680
- def check_single(vs: ta.Iterable[T]) -> T:
681
- [v] = vs
682
- return v
1031
+ #
683
1032
 
1033
+ def arg(self, v: bool, msg: CheckMessage = None) -> None:
1034
+ if not v:
1035
+ self._raise(
1036
+ RuntimeError,
1037
+ 'Argument condition not met',
1038
+ msg,
1039
+ Checks._ArgsKwargs(v),
1040
+ render_fmt='%s',
1041
+ )
684
1042
 
685
- def check_empty(v: SizedT) -> SizedT:
686
- if len(v):
687
- raise ValueError(v)
688
- return v
1043
+ def state(self, v: bool, msg: CheckMessage = None) -> None:
1044
+ if not v:
1045
+ self._raise(
1046
+ RuntimeError,
1047
+ 'State condition not met',
1048
+ msg,
1049
+ Checks._ArgsKwargs(v),
1050
+ render_fmt='%s',
1051
+ )
689
1052
 
690
1053
 
691
- def check_non_empty(v: SizedT) -> SizedT:
692
- if not len(v):
693
- raise ValueError(v)
694
- return v
1054
+ check = Checks()
695
1055
 
696
1056
 
697
1057
  ########################################
@@ -1951,7 +2311,7 @@ async def asyncio_subprocess_popen(
1951
2311
  if shell:
1952
2312
  fac = functools.partial(
1953
2313
  asyncio.create_subprocess_shell,
1954
- check_single(cmd),
2314
+ check.single(cmd),
1955
2315
  )
1956
2316
  else:
1957
2317
  fac = functools.partial(
@@ -1991,7 +2351,7 @@ class AsyncioProcessCommunicator:
1991
2351
  self._proc = proc
1992
2352
  self._loop = loop
1993
2353
 
1994
- self._transport: asyncio.base_subprocess.BaseSubprocessTransport = check_isinstance(
2354
+ self._transport: asyncio.base_subprocess.BaseSubprocessTransport = check.isinstance(
1995
2355
  proc._transport, # type: ignore # noqa
1996
2356
  asyncio.base_subprocess.BaseSubprocessTransport,
1997
2357
  )
@@ -2001,7 +2361,7 @@ class AsyncioProcessCommunicator:
2001
2361
  return self._loop.get_debug()
2002
2362
 
2003
2363
  async def _feed_stdin(self, input: bytes) -> None: # noqa
2004
- stdin = check_not_none(self._proc.stdin)
2364
+ stdin = check.not_none(self._proc.stdin)
2005
2365
  try:
2006
2366
  if input is not None:
2007
2367
  stdin.write(input)
@@ -2025,13 +2385,13 @@ class AsyncioProcessCommunicator:
2025
2385
  return None
2026
2386
 
2027
2387
  async def _read_stream(self, fd: int) -> bytes:
2028
- transport: ta.Any = check_not_none(self._transport.get_pipe_transport(fd))
2388
+ transport: ta.Any = check.not_none(self._transport.get_pipe_transport(fd))
2029
2389
 
2030
2390
  if fd == 2:
2031
- stream = check_not_none(self._proc.stderr)
2391
+ stream = check.not_none(self._proc.stderr)
2032
2392
  else:
2033
- check_equal(fd, 1)
2034
- stream = check_not_none(self._proc.stdout)
2393
+ check.equal(fd, 1)
2394
+ stream = check.not_none(self._proc.stdout)
2035
2395
 
2036
2396
  if self._debug:
2037
2397
  name = 'stdout' if fd == 1 else 'stderr'
@@ -2151,7 +2511,7 @@ async def asyncio_subprocess_check_output(
2151
2511
  **kwargs,
2152
2512
  )
2153
2513
 
2154
- return check_not_none(stdout)
2514
+ return check.not_none(stdout)
2155
2515
 
2156
2516
 
2157
2517
  async def asyncio_subprocess_check_output_str(*args: str, **kwargs: ta.Any) -> str:
@@ -2415,7 +2775,7 @@ class Pyenv:
2415
2775
 
2416
2776
  @async_cached_nullary
2417
2777
  async def exe(self) -> str:
2418
- return os.path.join(check_not_none(await self.root()), 'bin', 'pyenv')
2778
+ return os.path.join(check.not_none(await self.root()), 'bin', 'pyenv')
2419
2779
 
2420
2780
  async def version_exes(self) -> ta.List[ta.Tuple[str, str]]:
2421
2781
  if (root := await self.root()) is None:
@@ -2641,7 +3001,7 @@ class PyenvVersionInstaller:
2641
3001
 
2642
3002
  @async_cached_nullary
2643
3003
  async def install_dir(self) -> str:
2644
- return str(os.path.join(check_not_none(await self._pyenv.root()), 'versions', self.install_name()))
3004
+ return str(os.path.join(check.not_none(await self._pyenv.root()), 'versions', self.install_name()))
2645
3005
 
2646
3006
  @async_cached_nullary
2647
3007
  async def install(self) -> str:
@@ -2664,7 +3024,7 @@ class PyenvVersionInstaller:
2664
3024
 
2665
3025
  if self._given_install_name is not None:
2666
3026
  full_args = [
2667
- os.path.join(check_not_none(await self._pyenv.root()), 'plugins', 'python-build', 'bin', 'python-build'), # noqa
3027
+ os.path.join(check.not_none(await self._pyenv.root()), 'plugins', 'python-build', 'bin', 'python-build'), # noqa
2668
3028
  *conf_args,
2669
3029
  self.install_dir(),
2670
3030
  ]
@@ -2736,7 +3096,7 @@ class PyenvInterpProvider(InterpProvider):
2736
3096
  iv: ta.Optional[InterpVersion]
2737
3097
  if self._inspect:
2738
3098
  try:
2739
- iv = check_not_none(await self._inspector.inspect(ep)).iv
3099
+ iv = check.not_none(await self._inspector.inspect(ep)).iv
2740
3100
  except Exception as e: # noqa
2741
3101
  return None
2742
3102
  else:
@@ -3040,7 +3400,7 @@ async def _resolve_cmd(args) -> None:
3040
3400
  else:
3041
3401
  r = DEFAULT_INTERP_RESOLVER
3042
3402
  s = InterpSpecifier.parse(args.version)
3043
- print(check_not_none(await r.resolve(s, install=bool(args.install))).exe)
3403
+ print(check.not_none(await r.resolve(s, install=bool(args.install))).exe)
3044
3404
 
3045
3405
 
3046
3406
  def _build_parser() -> argparse.ArgumentParser: