omdev 0.0.0.dev149__py3-none-any.whl → 0.0.0.dev151__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
@@ -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] # ta.TypeAlias
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,104 +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
602
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
+ )
603
771
 
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
772
+ return v
608
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)
609
777
 
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
778
+ return inner
614
779
 
780
+ ##
615
781
 
616
- def check_none(v: T) -> None:
617
- if v is not None:
618
- raise ValueError(v)
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
+ )
619
791
 
792
+ return v
620
793
 
621
- def check_not_none(v: ta.Optional[T]) -> T:
622
- if v is None:
623
- raise ValueError
624
- return v
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
+ )
625
803
 
804
+ return v
626
805
 
627
- def check_not(v: ta.Any) -> None:
628
- if v:
629
- raise ValueError(v)
630
- return v
806
+ #
631
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
+ )
632
817
 
633
- def check_non_empty_str(v: ta.Optional[str]) -> str:
634
- if not v:
635
- raise ValueError
636
- return v
818
+ return v
637
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
+ )
638
829
 
639
- def check_arg(v: bool, msg: str = 'Illegal argument') -> None:
640
- if not v:
641
- raise ValueError(msg)
830
+ return v
642
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
+ )
643
841
 
644
- def check_state(v: bool, msg: str = 'Illegal state') -> None:
645
- if not v:
646
- raise ValueError(msg)
842
+ return v
647
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
+ )
648
858
 
649
- def check_equal(l: T, r: T) -> T:
650
- if l != r:
651
- raise ValueError(l, r)
652
- return l
859
+ return v
653
860
 
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
+ )
654
870
 
655
- def check_not_equal(l: T, r: T) -> T:
656
- if l == r:
657
- raise ValueError(l, r)
658
- return l
871
+ return v
659
872
 
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
+ )
660
882
 
661
- def check_is(l: T, r: T) -> T:
662
- if l is not r:
663
- raise ValueError(l, r)
664
- return l
883
+ return it
665
884
 
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
+ )
896
+
897
+ return value
898
+
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
666
905
 
667
- def check_is_not(l: T, r: ta.Any) -> T:
668
- if l is r:
669
- raise ValueError(l, r)
670
- return l
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
+ )
671
918
 
919
+ raise RuntimeError # noqa
672
920
 
673
- def check_in(v: T, c: ta.Container[T]) -> T:
674
- if v not in c:
675
- raise ValueError(v, c)
676
- return v
921
+ #
677
922
 
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
+ )
678
932
 
679
- def check_not_in(v: T, c: ta.Container[T]) -> T:
680
- if v in c:
681
- raise ValueError(v, c)
682
- return v
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
+ )
683
942
 
943
+ return v
684
944
 
685
- def check_single(vs: ta.Iterable[T]) -> T:
686
- [v] = vs
687
- return v
945
+ #
688
946
 
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
+ )
689
956
 
690
- def check_empty(v: SizedT) -> SizedT:
691
- if len(v):
692
- raise ValueError(v)
693
- return v
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
+ )
968
+
969
+ return v
970
+
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
+ )
980
+
981
+ return v
982
+
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
+ )
992
+
993
+ return v # type: ignore
994
+
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
+ )
1004
+
1005
+ return v
1006
+
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
+ )
1016
+
1017
+ return new
1018
+
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
+ )
1028
+
1029
+ return new
1030
+
1031
+ #
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
+ )
1042
+
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
+ )
694
1052
 
695
1053
 
696
- def check_not_empty(v: SizedT) -> SizedT:
697
- if not len(v):
698
- raise ValueError(v)
699
- return v
1054
+ check = Checks()
700
1055
 
701
1056
 
702
1057
  ########################################
@@ -1956,7 +2311,7 @@ async def asyncio_subprocess_popen(
1956
2311
  if shell:
1957
2312
  fac = functools.partial(
1958
2313
  asyncio.create_subprocess_shell,
1959
- check_single(cmd),
2314
+ check.single(cmd),
1960
2315
  )
1961
2316
  else:
1962
2317
  fac = functools.partial(
@@ -1996,7 +2351,7 @@ class AsyncioProcessCommunicator:
1996
2351
  self._proc = proc
1997
2352
  self._loop = loop
1998
2353
 
1999
- self._transport: asyncio.base_subprocess.BaseSubprocessTransport = check_isinstance(
2354
+ self._transport: asyncio.base_subprocess.BaseSubprocessTransport = check.isinstance(
2000
2355
  proc._transport, # type: ignore # noqa
2001
2356
  asyncio.base_subprocess.BaseSubprocessTransport,
2002
2357
  )
@@ -2006,7 +2361,7 @@ class AsyncioProcessCommunicator:
2006
2361
  return self._loop.get_debug()
2007
2362
 
2008
2363
  async def _feed_stdin(self, input: bytes) -> None: # noqa
2009
- stdin = check_not_none(self._proc.stdin)
2364
+ stdin = check.not_none(self._proc.stdin)
2010
2365
  try:
2011
2366
  if input is not None:
2012
2367
  stdin.write(input)
@@ -2030,13 +2385,13 @@ class AsyncioProcessCommunicator:
2030
2385
  return None
2031
2386
 
2032
2387
  async def _read_stream(self, fd: int) -> bytes:
2033
- 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))
2034
2389
 
2035
2390
  if fd == 2:
2036
- stream = check_not_none(self._proc.stderr)
2391
+ stream = check.not_none(self._proc.stderr)
2037
2392
  else:
2038
- check_equal(fd, 1)
2039
- stream = check_not_none(self._proc.stdout)
2393
+ check.equal(fd, 1)
2394
+ stream = check.not_none(self._proc.stdout)
2040
2395
 
2041
2396
  if self._debug:
2042
2397
  name = 'stdout' if fd == 1 else 'stderr'
@@ -2156,7 +2511,7 @@ async def asyncio_subprocess_check_output(
2156
2511
  **kwargs,
2157
2512
  )
2158
2513
 
2159
- return check_not_none(stdout)
2514
+ return check.not_none(stdout)
2160
2515
 
2161
2516
 
2162
2517
  async def asyncio_subprocess_check_output_str(*args: str, **kwargs: ta.Any) -> str:
@@ -2420,7 +2775,7 @@ class Pyenv:
2420
2775
 
2421
2776
  @async_cached_nullary
2422
2777
  async def exe(self) -> str:
2423
- 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')
2424
2779
 
2425
2780
  async def version_exes(self) -> ta.List[ta.Tuple[str, str]]:
2426
2781
  if (root := await self.root()) is None:
@@ -2646,7 +3001,7 @@ class PyenvVersionInstaller:
2646
3001
 
2647
3002
  @async_cached_nullary
2648
3003
  async def install_dir(self) -> str:
2649
- 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()))
2650
3005
 
2651
3006
  @async_cached_nullary
2652
3007
  async def install(self) -> str:
@@ -2669,7 +3024,7 @@ class PyenvVersionInstaller:
2669
3024
 
2670
3025
  if self._given_install_name is not None:
2671
3026
  full_args = [
2672
- 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
2673
3028
  *conf_args,
2674
3029
  self.install_dir(),
2675
3030
  ]
@@ -2741,7 +3096,7 @@ class PyenvInterpProvider(InterpProvider):
2741
3096
  iv: ta.Optional[InterpVersion]
2742
3097
  if self._inspect:
2743
3098
  try:
2744
- iv = check_not_none(await self._inspector.inspect(ep)).iv
3099
+ iv = check.not_none(await self._inspector.inspect(ep)).iv
2745
3100
  except Exception as e: # noqa
2746
3101
  return None
2747
3102
  else:
@@ -3045,7 +3400,7 @@ async def _resolve_cmd(args) -> None:
3045
3400
  else:
3046
3401
  r = DEFAULT_INTERP_RESOLVER
3047
3402
  s = InterpSpecifier.parse(args.version)
3048
- 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)
3049
3404
 
3050
3405
 
3051
3406
  def _build_parser() -> argparse.ArgumentParser: