omlish 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.
- omlish/__about__.py +2 -2
- omlish/argparse/cli.py +19 -23
- omlish/check.py +49 -464
- omlish/docker/__init__.py +0 -37
- omlish/docker/all.py +31 -0
- omlish/docker/consts.py +4 -0
- omlish/{lite/docker.py → docker/detect.py} +16 -1
- omlish/docker/{helpers.py → timebomb.py} +0 -15
- omlish/http/__init__.py +0 -48
- omlish/http/all.py +48 -0
- omlish/{lite/http → http}/coroserver.py +11 -12
- omlish/{lite/http → http}/handlers.py +2 -1
- omlish/{lite/http → http}/parsing.py +1 -0
- omlish/{lite/http → http}/versions.py +1 -0
- omlish/io/buffers.py +6 -8
- omlish/io/fdio/corohttp.py +10 -13
- omlish/io/fdio/handlers.py +2 -2
- omlish/lite/asyncio/subprocesses.py +9 -12
- omlish/lite/check.py +438 -80
- omlish/lite/contextmanagers.py +3 -4
- omlish/lite/inject.py +12 -16
- omlish/lite/marshal.py +7 -8
- omlish/lite/socketserver.py +2 -2
- omlish/testing/pytest/plugins/switches.py +1 -1
- {omlish-0.0.0.dev149.dist-info → omlish-0.0.0.dev151.dist-info}/METADATA +1 -1
- {omlish-0.0.0.dev149.dist-info → omlish-0.0.0.dev151.dist-info}/RECORD +30 -28
- omlish/lite/http/__init__.py +0 -0
- {omlish-0.0.0.dev149.dist-info → omlish-0.0.0.dev151.dist-info}/LICENSE +0 -0
- {omlish-0.0.0.dev149.dist-info → omlish-0.0.0.dev151.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev149.dist-info → omlish-0.0.0.dev151.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev149.dist-info → omlish-0.0.0.dev151.dist-info}/top_level.txt +0 -0
    
        omlish/lite/check.py
    CHANGED
    
    | @@ -1,104 +1,462 @@ | |
| 1 1 | 
             
            # ruff: noqa: UP006 UP007
         | 
| 2 | 
            +
            """
         | 
| 3 | 
            +
            TODO:
         | 
| 4 | 
            +
             - def maybe(v: lang.Maybe[T])
         | 
| 5 | 
            +
             - patch / override lite.check ?
         | 
| 6 | 
            +
              - checker interface?
         | 
| 7 | 
            +
            """
         | 
| 8 | 
            +
            import collections
         | 
| 9 | 
            +
            import threading
         | 
| 2 10 | 
             
            import typing as ta
         | 
| 3 11 |  | 
| 4 12 |  | 
| 5 13 | 
             
            T = ta.TypeVar('T')
         | 
| 6 14 | 
             
            SizedT = ta.TypeVar('SizedT', bound=ta.Sized)
         | 
| 7 15 |  | 
| 16 | 
            +
            CheckMessage = ta.Union[str, ta.Callable[..., ta.Optional[str]], None]  # ta.TypeAlias
         | 
| 17 | 
            +
            CheckLateConfigureFn = ta.Callable[['Checks'], None]  # ta.TypeAlias
         | 
| 18 | 
            +
            CheckOnRaiseFn = ta.Callable[[Exception], None]  # ta.TypeAlias
         | 
| 19 | 
            +
            CheckExceptionFactory = ta.Callable[..., Exception]  # ta.TypeAlias
         | 
| 20 | 
            +
            CheckArgsRenderer = ta.Callable[..., ta.Optional[str]]  # ta.TypeAlias
         | 
| 8 21 |  | 
| 9 | 
            -
            def check_isinstance(v: ta.Any, spec: ta.Union[ta.Type[T], tuple]) -> T:
         | 
| 10 | 
            -
                if not isinstance(v, spec):
         | 
| 11 | 
            -
                    raise TypeError(v)
         | 
| 12 | 
            -
                return v
         | 
| 13 22 |  | 
| 23 | 
            +
            ##
         | 
| 14 24 |  | 
| 15 | 
            -
            def check_not_isinstance(v: T, spec: ta.Union[type, tuple]) -> T:
         | 
| 16 | 
            -
                if isinstance(v, spec):
         | 
| 17 | 
            -
                    raise TypeError(v)
         | 
| 18 | 
            -
                return v
         | 
| 19 25 |  | 
| 26 | 
            +
            class Checks:
         | 
| 27 | 
            +
                def __init__(self) -> None:
         | 
| 28 | 
            +
                    super().__init__()
         | 
| 20 29 |  | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
                     | 
| 30 | 
            +
                    self._config_lock = threading.RLock()
         | 
| 31 | 
            +
                    self._on_raise_fns: ta.Sequence[CheckOnRaiseFn] = []
         | 
| 32 | 
            +
                    self._exception_factory: CheckExceptionFactory = Checks.default_exception_factory
         | 
| 33 | 
            +
                    self._args_renderer: ta.Optional[CheckArgsRenderer] = None
         | 
| 34 | 
            +
                    self._late_configure_fns: ta.Sequence[CheckLateConfigureFn] = []
         | 
| 24 35 |  | 
| 36 | 
            +
                @staticmethod
         | 
| 37 | 
            +
                def default_exception_factory(exc_cls: ta.Type[Exception], *args, **kwargs) -> Exception:
         | 
| 38 | 
            +
                    return exc_cls(*args, **kwargs)  # noqa
         | 
| 25 39 |  | 
| 26 | 
            -
             | 
| 27 | 
            -
                if v is None:
         | 
| 28 | 
            -
                    raise ValueError
         | 
| 29 | 
            -
                return v
         | 
| 40 | 
            +
                #
         | 
| 30 41 |  | 
| 42 | 
            +
                def register_on_raise(self, fn: CheckOnRaiseFn) -> None:
         | 
| 43 | 
            +
                    with self._config_lock:
         | 
| 44 | 
            +
                        self._on_raise_fns = [*self._on_raise_fns, fn]
         | 
| 31 45 |  | 
| 32 | 
            -
            def  | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
                return v
         | 
| 46 | 
            +
                def unregister_on_raise(self, fn: CheckOnRaiseFn) -> None:
         | 
| 47 | 
            +
                    with self._config_lock:
         | 
| 48 | 
            +
                        self._on_raise_fns = [e for e in self._on_raise_fns if e != fn]
         | 
| 36 49 |  | 
| 50 | 
            +
                #
         | 
| 37 51 |  | 
| 38 | 
            -
            def  | 
| 39 | 
            -
             | 
| 40 | 
            -
                    raise ValueError
         | 
| 41 | 
            -
                return v
         | 
| 52 | 
            +
                def set_exception_factory(self, factory: CheckExceptionFactory) -> None:
         | 
| 53 | 
            +
                    self._exception_factory = factory
         | 
| 42 54 |  | 
| 55 | 
            +
                def set_args_renderer(self, renderer: ta.Optional[CheckArgsRenderer]) -> None:
         | 
| 56 | 
            +
                    self._args_renderer = renderer
         | 
| 43 57 |  | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
| 58 | 
            +
                #
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                def register_late_configure(self, fn: CheckLateConfigureFn) -> None:
         | 
| 61 | 
            +
                    with self._config_lock:
         | 
| 62 | 
            +
                        self._late_configure_fns = [*self._late_configure_fns, fn]
         | 
| 47 63 |  | 
| 64 | 
            +
                def _late_configure(self) -> None:
         | 
| 65 | 
            +
                    if not self._late_configure_fns:
         | 
| 66 | 
            +
                        return
         | 
| 48 67 |  | 
| 49 | 
            -
             | 
| 50 | 
            -
             | 
| 51 | 
            -
             | 
| 68 | 
            +
                    with self._config_lock:
         | 
| 69 | 
            +
                        if not (lc := self._late_configure_fns):
         | 
| 70 | 
            +
                            return
         | 
| 52 71 |  | 
| 72 | 
            +
                        for fn in lc:
         | 
| 73 | 
            +
                            fn(self)
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                        self._late_configure_fns = []
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                #
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                class _ArgsKwargs:
         | 
| 80 | 
            +
                    def __init__(self, *args, **kwargs):
         | 
| 81 | 
            +
                        self.args = args
         | 
| 82 | 
            +
                        self.kwargs = kwargs
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                def _raise(
         | 
| 85 | 
            +
                        self,
         | 
| 86 | 
            +
                        exception_type: ta.Type[Exception],
         | 
| 87 | 
            +
                        default_message: str,
         | 
| 88 | 
            +
                        message: CheckMessage,
         | 
| 89 | 
            +
                        ak: _ArgsKwargs = _ArgsKwargs(),
         | 
| 90 | 
            +
                        *,
         | 
| 91 | 
            +
                        render_fmt: ta.Optional[str] = None,
         | 
| 92 | 
            +
                ) -> ta.NoReturn:
         | 
| 93 | 
            +
                    exc_args = ()
         | 
| 94 | 
            +
                    if callable(message):
         | 
| 95 | 
            +
                        message = ta.cast(ta.Callable, message)(*ak.args, **ak.kwargs)
         | 
| 96 | 
            +
                        if isinstance(message, tuple):
         | 
| 97 | 
            +
                            message, *exc_args = message  # type: ignore
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                    if message is None:
         | 
| 100 | 
            +
                        message = default_message
         | 
| 53 101 |  | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
                     | 
| 57 | 
            -
             | 
| 58 | 
            -
             | 
| 59 | 
            -
             | 
| 60 | 
            -
             | 
| 61 | 
            -
             | 
| 62 | 
            -
             | 
| 63 | 
            -
             | 
| 64 | 
            -
             | 
| 65 | 
            -
             | 
| 66 | 
            -
             | 
| 67 | 
            -
             | 
| 68 | 
            -
             | 
| 69 | 
            -
             | 
| 70 | 
            -
             | 
| 71 | 
            -
             | 
| 72 | 
            -
             | 
| 73 | 
            -
             | 
| 74 | 
            -
             | 
| 75 | 
            -
             | 
| 76 | 
            -
             | 
| 77 | 
            -
             | 
| 78 | 
            -
             | 
| 79 | 
            -
             | 
| 80 | 
            -
             | 
| 81 | 
            -
             | 
| 82 | 
            -
             | 
| 83 | 
            -
             | 
| 84 | 
            -
             | 
| 85 | 
            -
             | 
| 86 | 
            -
             | 
| 87 | 
            -
                 | 
| 88 | 
            -
             | 
| 89 | 
            -
             | 
| 90 | 
            -
             | 
| 91 | 
            -
             | 
| 92 | 
            -
             | 
| 93 | 
            -
             | 
| 94 | 
            -
             | 
| 95 | 
            -
             | 
| 96 | 
            -
             | 
| 97 | 
            -
                     | 
| 98 | 
            -
             | 
| 99 | 
            -
             | 
| 100 | 
            -
             | 
| 101 | 
            -
             | 
| 102 | 
            -
             | 
| 103 | 
            -
                     | 
| 104 | 
            -
             | 
| 102 | 
            +
                    self._late_configure()
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                    if render_fmt is not None and (af := self._args_renderer) is not None:
         | 
| 105 | 
            +
                        rendered_args = af(render_fmt, *ak.args)
         | 
| 106 | 
            +
                        if rendered_args is not None:
         | 
| 107 | 
            +
                            message = f'{message} : {rendered_args}'
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                    exc = self._exception_factory(
         | 
| 110 | 
            +
                        exception_type,
         | 
| 111 | 
            +
                        message,
         | 
| 112 | 
            +
                        *exc_args,
         | 
| 113 | 
            +
                        *ak.args,
         | 
| 114 | 
            +
                        **ak.kwargs,
         | 
| 115 | 
            +
                    )
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                    for fn in self._on_raise_fns:
         | 
| 118 | 
            +
                        fn(exc)
         | 
| 119 | 
            +
             | 
| 120 | 
            +
                    raise exc
         | 
| 121 | 
            +
             | 
| 122 | 
            +
                #
         | 
| 123 | 
            +
             | 
| 124 | 
            +
                def _unpack_isinstance_spec(self, spec: ta.Any) -> tuple:
         | 
| 125 | 
            +
                    if isinstance(spec, type):
         | 
| 126 | 
            +
                        return (spec,)
         | 
| 127 | 
            +
                    if not isinstance(spec, tuple):
         | 
| 128 | 
            +
                        spec = (spec,)
         | 
| 129 | 
            +
                    if None in spec:
         | 
| 130 | 
            +
                        spec = tuple(filter(None, spec)) + (None.__class__,)  # noqa
         | 
| 131 | 
            +
                    if ta.Any in spec:
         | 
| 132 | 
            +
                        spec = (object,)
         | 
| 133 | 
            +
                    return spec
         | 
| 134 | 
            +
             | 
| 135 | 
            +
                def isinstance(self, v: ta.Any, spec: ta.Union[ta.Type[T], tuple], msg: CheckMessage = None) -> T:  # noqa
         | 
| 136 | 
            +
                    if not isinstance(v, self._unpack_isinstance_spec(spec)):
         | 
| 137 | 
            +
                        self._raise(
         | 
| 138 | 
            +
                            TypeError,
         | 
| 139 | 
            +
                            'Must be instance',
         | 
| 140 | 
            +
                            msg,
         | 
| 141 | 
            +
                            Checks._ArgsKwargs(v, spec),
         | 
| 142 | 
            +
                            render_fmt='not isinstance(%s, %s)',
         | 
| 143 | 
            +
                        )
         | 
| 144 | 
            +
             | 
| 145 | 
            +
                    return v
         | 
| 146 | 
            +
             | 
| 147 | 
            +
                def of_isinstance(self, spec: ta.Union[ta.Type[T], tuple], msg: CheckMessage = None) -> ta.Callable[[ta.Any], T]:
         | 
| 148 | 
            +
                    def inner(v):
         | 
| 149 | 
            +
                        return self.isinstance(v, self._unpack_isinstance_spec(spec), msg)
         | 
| 150 | 
            +
             | 
| 151 | 
            +
                    return inner
         | 
| 152 | 
            +
             | 
| 153 | 
            +
                def cast(self, v: ta.Any, cls: ta.Type[T], msg: CheckMessage = None) -> T:  # noqa
         | 
| 154 | 
            +
                    if not isinstance(v, cls):
         | 
| 155 | 
            +
                        self._raise(
         | 
| 156 | 
            +
                            TypeError,
         | 
| 157 | 
            +
                            'Must be instance',
         | 
| 158 | 
            +
                            msg,
         | 
| 159 | 
            +
                            Checks._ArgsKwargs(v, cls),
         | 
| 160 | 
            +
                        )
         | 
| 161 | 
            +
             | 
| 162 | 
            +
                    return v
         | 
| 163 | 
            +
             | 
| 164 | 
            +
                def of_cast(self, cls: ta.Type[T], msg: CheckMessage = None) -> ta.Callable[[T], T]:
         | 
| 165 | 
            +
                    def inner(v):
         | 
| 166 | 
            +
                        return self.cast(v, cls, msg)
         | 
| 167 | 
            +
             | 
| 168 | 
            +
                    return inner
         | 
| 169 | 
            +
             | 
| 170 | 
            +
                def not_isinstance(self, v: T, spec: ta.Any, msg: CheckMessage = None) -> T:  # noqa
         | 
| 171 | 
            +
                    if isinstance(v, self._unpack_isinstance_spec(spec)):
         | 
| 172 | 
            +
                        self._raise(
         | 
| 173 | 
            +
                            TypeError,
         | 
| 174 | 
            +
                            'Must not be instance',
         | 
| 175 | 
            +
                            msg,
         | 
| 176 | 
            +
                            Checks._ArgsKwargs(v, spec),
         | 
| 177 | 
            +
                            render_fmt='isinstance(%s, %s)',
         | 
| 178 | 
            +
                        )
         | 
| 179 | 
            +
             | 
| 180 | 
            +
                    return v
         | 
| 181 | 
            +
             | 
| 182 | 
            +
                def of_not_isinstance(self, spec: ta.Any, msg: CheckMessage = None) -> ta.Callable[[T], T]:
         | 
| 183 | 
            +
                    def inner(v):
         | 
| 184 | 
            +
                        return self.not_isinstance(v, self._unpack_isinstance_spec(spec), msg)
         | 
| 185 | 
            +
             | 
| 186 | 
            +
                    return inner
         | 
| 187 | 
            +
             | 
| 188 | 
            +
                ##
         | 
| 189 | 
            +
             | 
| 190 | 
            +
                def issubclass(self, v: ta.Type[T], spec: ta.Any, msg: CheckMessage = None) -> ta.Type[T]:  # noqa
         | 
| 191 | 
            +
                    if not issubclass(v, spec):
         | 
| 192 | 
            +
                        self._raise(
         | 
| 193 | 
            +
                            TypeError,
         | 
| 194 | 
            +
                            'Must be subclass',
         | 
| 195 | 
            +
                            msg,
         | 
| 196 | 
            +
                            Checks._ArgsKwargs(v, spec),
         | 
| 197 | 
            +
                            render_fmt='not issubclass(%s, %s)',
         | 
| 198 | 
            +
                        )
         | 
| 199 | 
            +
             | 
| 200 | 
            +
                    return v
         | 
| 201 | 
            +
             | 
| 202 | 
            +
                def not_issubclass(self, v: ta.Type[T], spec: ta.Any, msg: CheckMessage = None) -> ta.Type[T]:  # noqa
         | 
| 203 | 
            +
                    if issubclass(v, spec):
         | 
| 204 | 
            +
                        self._raise(
         | 
| 205 | 
            +
                            TypeError,
         | 
| 206 | 
            +
                            'Must not be subclass',
         | 
| 207 | 
            +
                            msg,
         | 
| 208 | 
            +
                            Checks._ArgsKwargs(v, spec),
         | 
| 209 | 
            +
                            render_fmt='issubclass(%s, %s)',
         | 
| 210 | 
            +
                        )
         | 
| 211 | 
            +
             | 
| 212 | 
            +
                    return v
         | 
| 213 | 
            +
             | 
| 214 | 
            +
                #
         | 
| 215 | 
            +
             | 
| 216 | 
            +
                def in_(self, v: T, c: ta.Container[T], msg: CheckMessage = None) -> T:
         | 
| 217 | 
            +
                    if v not in c:
         | 
| 218 | 
            +
                        self._raise(
         | 
| 219 | 
            +
                            ValueError,
         | 
| 220 | 
            +
                            'Must be in',
         | 
| 221 | 
            +
                            msg,
         | 
| 222 | 
            +
                            Checks._ArgsKwargs(v, c),
         | 
| 223 | 
            +
                            render_fmt='%s not in %s',
         | 
| 224 | 
            +
                        )
         | 
| 225 | 
            +
             | 
| 226 | 
            +
                    return v
         | 
| 227 | 
            +
             | 
| 228 | 
            +
                def not_in(self, v: T, c: ta.Container[T], msg: CheckMessage = None) -> T:
         | 
| 229 | 
            +
                    if v in c:
         | 
| 230 | 
            +
                        self._raise(
         | 
| 231 | 
            +
                            ValueError,
         | 
| 232 | 
            +
                            'Must not be in',
         | 
| 233 | 
            +
                            msg,
         | 
| 234 | 
            +
                            Checks._ArgsKwargs(v, c),
         | 
| 235 | 
            +
                            render_fmt='%s in %s',
         | 
| 236 | 
            +
                        )
         | 
| 237 | 
            +
             | 
| 238 | 
            +
                    return v
         | 
| 239 | 
            +
             | 
| 240 | 
            +
                def empty(self, v: SizedT, msg: CheckMessage = None) -> SizedT:
         | 
| 241 | 
            +
                    if len(v) != 0:
         | 
| 242 | 
            +
                        self._raise(
         | 
| 243 | 
            +
                            ValueError,
         | 
| 244 | 
            +
                            'Must be empty',
         | 
| 245 | 
            +
                            msg,
         | 
| 246 | 
            +
                            Checks._ArgsKwargs(v),
         | 
| 247 | 
            +
                            render_fmt='%s',
         | 
| 248 | 
            +
                        )
         | 
| 249 | 
            +
             | 
| 250 | 
            +
                    return v
         | 
| 251 | 
            +
             | 
| 252 | 
            +
                def iterempty(self, v: ta.Iterable[T], msg: CheckMessage = None) -> ta.Iterable[T]:
         | 
| 253 | 
            +
                    it = iter(v)
         | 
| 254 | 
            +
                    try:
         | 
| 255 | 
            +
                        next(it)
         | 
| 256 | 
            +
                    except StopIteration:
         | 
| 257 | 
            +
                        pass
         | 
| 258 | 
            +
                    else:
         | 
| 259 | 
            +
                        self._raise(
         | 
| 260 | 
            +
                            ValueError,
         | 
| 261 | 
            +
                            'Must be empty',
         | 
| 262 | 
            +
                            msg,
         | 
| 263 | 
            +
                            Checks._ArgsKwargs(v),
         | 
| 264 | 
            +
                            render_fmt='%s',
         | 
| 265 | 
            +
                        )
         | 
| 266 | 
            +
             | 
| 267 | 
            +
                    return v
         | 
| 268 | 
            +
             | 
| 269 | 
            +
                def not_empty(self, v: SizedT, msg: CheckMessage = None) -> SizedT:
         | 
| 270 | 
            +
                    if len(v) == 0:
         | 
| 271 | 
            +
                        self._raise(
         | 
| 272 | 
            +
                            ValueError,
         | 
| 273 | 
            +
                            'Must not be empty',
         | 
| 274 | 
            +
                            msg,
         | 
| 275 | 
            +
                            Checks._ArgsKwargs(v),
         | 
| 276 | 
            +
                            render_fmt='%s',
         | 
| 277 | 
            +
                        )
         | 
| 278 | 
            +
             | 
| 279 | 
            +
                    return v
         | 
| 280 | 
            +
             | 
| 281 | 
            +
                def unique(self, it: ta.Iterable[T], msg: CheckMessage = None) -> ta.Iterable[T]:
         | 
| 282 | 
            +
                    dupes = [e for e, c in collections.Counter(it).items() if c > 1]
         | 
| 283 | 
            +
                    if dupes:
         | 
| 284 | 
            +
                        self._raise(
         | 
| 285 | 
            +
                            ValueError,
         | 
| 286 | 
            +
                            'Must be unique',
         | 
| 287 | 
            +
                            msg,
         | 
| 288 | 
            +
                            Checks._ArgsKwargs(it, dupes),
         | 
| 289 | 
            +
                        )
         | 
| 290 | 
            +
             | 
| 291 | 
            +
                    return it
         | 
| 292 | 
            +
             | 
| 293 | 
            +
                def single(self, obj: ta.Iterable[T], message: CheckMessage = None) -> T:
         | 
| 294 | 
            +
                    try:
         | 
| 295 | 
            +
                        [value] = obj
         | 
| 296 | 
            +
                    except ValueError:
         | 
| 297 | 
            +
                        self._raise(
         | 
| 298 | 
            +
                            ValueError,
         | 
| 299 | 
            +
                            'Must be single',
         | 
| 300 | 
            +
                            message,
         | 
| 301 | 
            +
                            Checks._ArgsKwargs(obj),
         | 
| 302 | 
            +
                            render_fmt='%s',
         | 
| 303 | 
            +
                        )
         | 
| 304 | 
            +
             | 
| 305 | 
            +
                    return value
         | 
| 306 | 
            +
             | 
| 307 | 
            +
                def opt_single(self, obj: ta.Iterable[T], message: CheckMessage = None) -> ta.Optional[T]:
         | 
| 308 | 
            +
                    it = iter(obj)
         | 
| 309 | 
            +
                    try:
         | 
| 310 | 
            +
                        value = next(it)
         | 
| 311 | 
            +
                    except StopIteration:
         | 
| 312 | 
            +
                        return None
         | 
| 313 | 
            +
             | 
| 314 | 
            +
                    try:
         | 
| 315 | 
            +
                        next(it)
         | 
| 316 | 
            +
                    except StopIteration:
         | 
| 317 | 
            +
                        return value  # noqa
         | 
| 318 | 
            +
             | 
| 319 | 
            +
                    self._raise(
         | 
| 320 | 
            +
                        ValueError,
         | 
| 321 | 
            +
                        'Must be empty or single',
         | 
| 322 | 
            +
                        message,
         | 
| 323 | 
            +
                        Checks._ArgsKwargs(obj),
         | 
| 324 | 
            +
                        render_fmt='%s',
         | 
| 325 | 
            +
                    )
         | 
| 326 | 
            +
             | 
| 327 | 
            +
                    raise RuntimeError  # noqa
         | 
| 328 | 
            +
             | 
| 329 | 
            +
                #
         | 
| 330 | 
            +
             | 
| 331 | 
            +
                def none(self, v: ta.Any, msg: CheckMessage = None) -> None:
         | 
| 332 | 
            +
                    if v is not None:
         | 
| 333 | 
            +
                        self._raise(
         | 
| 334 | 
            +
                            ValueError,
         | 
| 335 | 
            +
                            'Must be None',
         | 
| 336 | 
            +
                            msg,
         | 
| 337 | 
            +
                            Checks._ArgsKwargs(v),
         | 
| 338 | 
            +
                            render_fmt='%s',
         | 
| 339 | 
            +
                        )
         | 
| 340 | 
            +
             | 
| 341 | 
            +
                def not_none(self, v: ta.Optional[T], msg: CheckMessage = None) -> T:
         | 
| 342 | 
            +
                    if v is None:
         | 
| 343 | 
            +
                        self._raise(
         | 
| 344 | 
            +
                            ValueError,
         | 
| 345 | 
            +
                            'Must not be None',
         | 
| 346 | 
            +
                            msg,
         | 
| 347 | 
            +
                            Checks._ArgsKwargs(v),
         | 
| 348 | 
            +
                            render_fmt='%s',
         | 
| 349 | 
            +
                        )
         | 
| 350 | 
            +
             | 
| 351 | 
            +
                    return v
         | 
| 352 | 
            +
             | 
| 353 | 
            +
                #
         | 
| 354 | 
            +
             | 
| 355 | 
            +
                def equal(self, v: T, o: ta.Any, msg: CheckMessage = None) -> T:
         | 
| 356 | 
            +
                    if o != v:
         | 
| 357 | 
            +
                        self._raise(
         | 
| 358 | 
            +
                            ValueError,
         | 
| 359 | 
            +
                            'Must be equal',
         | 
| 360 | 
            +
                            msg,
         | 
| 361 | 
            +
                            Checks._ArgsKwargs(v, o),
         | 
| 362 | 
            +
                            render_fmt='%s != %s',
         | 
| 363 | 
            +
                        )
         | 
| 364 | 
            +
             | 
| 365 | 
            +
                    return v
         | 
| 366 | 
            +
             | 
| 367 | 
            +
                def is_(self, v: T, o: ta.Any, msg: CheckMessage = None) -> T:
         | 
| 368 | 
            +
                    if o is not v:
         | 
| 369 | 
            +
                        self._raise(
         | 
| 370 | 
            +
                            ValueError,
         | 
| 371 | 
            +
                            'Must be the same',
         | 
| 372 | 
            +
                            msg,
         | 
| 373 | 
            +
                            Checks._ArgsKwargs(v, o),
         | 
| 374 | 
            +
                            render_fmt='%s is not %s',
         | 
| 375 | 
            +
                        )
         | 
| 376 | 
            +
             | 
| 377 | 
            +
                    return v
         | 
| 378 | 
            +
             | 
| 379 | 
            +
                def is_not(self, v: T, o: ta.Any, msg: CheckMessage = None) -> T:
         | 
| 380 | 
            +
                    if o is v:
         | 
| 381 | 
            +
                        self._raise(
         | 
| 382 | 
            +
                            ValueError,
         | 
| 383 | 
            +
                            'Must not be the same',
         | 
| 384 | 
            +
                            msg,
         | 
| 385 | 
            +
                            Checks._ArgsKwargs(v, o),
         | 
| 386 | 
            +
                            render_fmt='%s is %s',
         | 
| 387 | 
            +
                        )
         | 
| 388 | 
            +
             | 
| 389 | 
            +
                    return v
         | 
| 390 | 
            +
             | 
| 391 | 
            +
                def callable(self, v: T, msg: CheckMessage = None) -> T:  # noqa
         | 
| 392 | 
            +
                    if not callable(v):
         | 
| 393 | 
            +
                        self._raise(
         | 
| 394 | 
            +
                            TypeError,
         | 
| 395 | 
            +
                            'Must be callable',
         | 
| 396 | 
            +
                            msg,
         | 
| 397 | 
            +
                            Checks._ArgsKwargs(v),
         | 
| 398 | 
            +
                            render_fmt='%s',
         | 
| 399 | 
            +
                        )
         | 
| 400 | 
            +
             | 
| 401 | 
            +
                    return v  # type: ignore
         | 
| 402 | 
            +
             | 
| 403 | 
            +
                def non_empty_str(self, v: ta.Optional[str], msg: CheckMessage = None) -> str:
         | 
| 404 | 
            +
                    if not isinstance(v, str) or not v:
         | 
| 405 | 
            +
                        self._raise(
         | 
| 406 | 
            +
                            ValueError,
         | 
| 407 | 
            +
                            'Must be non-empty str',
         | 
| 408 | 
            +
                            msg,
         | 
| 409 | 
            +
                            Checks._ArgsKwargs(v),
         | 
| 410 | 
            +
                            render_fmt='%s',
         | 
| 411 | 
            +
                        )
         | 
| 412 | 
            +
             | 
| 413 | 
            +
                    return v
         | 
| 414 | 
            +
             | 
| 415 | 
            +
                def replacing(self, expected: ta.Any, old: ta.Any, new: T, msg: CheckMessage = None) -> T:
         | 
| 416 | 
            +
                    if old != expected:
         | 
| 417 | 
            +
                        self._raise(
         | 
| 418 | 
            +
                            ValueError,
         | 
| 419 | 
            +
                            'Must be replacing',
         | 
| 420 | 
            +
                            msg,
         | 
| 421 | 
            +
                            Checks._ArgsKwargs(expected, old, new),
         | 
| 422 | 
            +
                            render_fmt='%s -> %s -> %s',
         | 
| 423 | 
            +
                        )
         | 
| 424 | 
            +
             | 
| 425 | 
            +
                    return new
         | 
| 426 | 
            +
             | 
| 427 | 
            +
                def replacing_none(self, old: ta.Any, new: T, msg: CheckMessage = None) -> T:
         | 
| 428 | 
            +
                    if old is not None:
         | 
| 429 | 
            +
                        self._raise(
         | 
| 430 | 
            +
                            ValueError,
         | 
| 431 | 
            +
                            'Must be replacing None',
         | 
| 432 | 
            +
                            msg,
         | 
| 433 | 
            +
                            Checks._ArgsKwargs(old, new),
         | 
| 434 | 
            +
                            render_fmt='%s -> %s',
         | 
| 435 | 
            +
                        )
         | 
| 436 | 
            +
             | 
| 437 | 
            +
                    return new
         | 
| 438 | 
            +
             | 
| 439 | 
            +
                #
         | 
| 440 | 
            +
             | 
| 441 | 
            +
                def arg(self, v: bool, msg: CheckMessage = None) -> None:
         | 
| 442 | 
            +
                    if not v:
         | 
| 443 | 
            +
                        self._raise(
         | 
| 444 | 
            +
                            RuntimeError,
         | 
| 445 | 
            +
                            'Argument condition not met',
         | 
| 446 | 
            +
                            msg,
         | 
| 447 | 
            +
                            Checks._ArgsKwargs(v),
         | 
| 448 | 
            +
                            render_fmt='%s',
         | 
| 449 | 
            +
                        )
         | 
| 450 | 
            +
             | 
| 451 | 
            +
                def state(self, v: bool, msg: CheckMessage = None) -> None:
         | 
| 452 | 
            +
                    if not v:
         | 
| 453 | 
            +
                        self._raise(
         | 
| 454 | 
            +
                            RuntimeError,
         | 
| 455 | 
            +
                            'State condition not met',
         | 
| 456 | 
            +
                            msg,
         | 
| 457 | 
            +
                            Checks._ArgsKwargs(v),
         | 
| 458 | 
            +
                            render_fmt='%s',
         | 
| 459 | 
            +
                        )
         | 
| 460 | 
            +
             | 
| 461 | 
            +
             | 
| 462 | 
            +
            check = Checks()
         | 
    
        omlish/lite/contextmanagers.py
    CHANGED
    
    | @@ -2,8 +2,7 @@ | |
| 2 2 | 
             
            import contextlib
         | 
| 3 3 | 
             
            import typing as ta
         | 
| 4 4 |  | 
| 5 | 
            -
            from .check import  | 
| 6 | 
            -
            from .check import check_state
         | 
| 5 | 
            +
            from .check import check
         | 
| 7 6 |  | 
| 8 7 |  | 
| 9 8 | 
             
            T = ta.TypeVar('T')
         | 
| @@ -17,7 +16,7 @@ class ExitStacked: | |
| 17 16 | 
             
                _exit_stack: ta.Optional[contextlib.ExitStack] = None
         | 
| 18 17 |  | 
| 19 18 | 
             
                def __enter__(self: ExitStackedT) -> ExitStackedT:
         | 
| 20 | 
            -
                     | 
| 19 | 
            +
                    check.state(self._exit_stack is None)
         | 
| 21 20 | 
             
                    es = self._exit_stack = contextlib.ExitStack()
         | 
| 22 21 | 
             
                    es.__enter__()
         | 
| 23 22 | 
             
                    return self
         | 
| @@ -32,7 +31,7 @@ class ExitStacked: | |
| 32 31 | 
             
                    pass
         | 
| 33 32 |  | 
| 34 33 | 
             
                def _enter_context(self, cm: ta.ContextManager[T]) -> T:
         | 
| 35 | 
            -
                    es =  | 
| 34 | 
            +
                    es = check.not_none(self._exit_stack)
         | 
| 36 35 | 
             
                    return es.enter_context(cm)
         | 
| 37 36 |  | 
| 38 37 |  | 
    
        omlish/lite/inject.py
    CHANGED
    
    | @@ -8,11 +8,7 @@ import types | |
| 8 8 | 
             
            import typing as ta
         | 
| 9 9 | 
             
            import weakref
         | 
| 10 10 |  | 
| 11 | 
            -
            from .check import  | 
| 12 | 
            -
            from .check import check_isinstance
         | 
| 13 | 
            -
            from .check import check_not_in
         | 
| 14 | 
            -
            from .check import check_not_isinstance
         | 
| 15 | 
            -
            from .check import check_not_none
         | 
| 11 | 
            +
            from .check import check
         | 
| 16 12 | 
             
            from .maybes import Maybe
         | 
| 17 13 | 
             
            from .reflect import get_optional_alias_arg
         | 
| 18 14 | 
             
            from .reflect import is_new_type
         | 
| @@ -170,7 +166,7 @@ class FnInjectorProvider(InjectorProvider): | |
| 170 166 | 
             
                fn: ta.Any
         | 
| 171 167 |  | 
| 172 168 | 
             
                def __post_init__(self) -> None:
         | 
| 173 | 
            -
                     | 
| 169 | 
            +
                    check.not_isinstance(self.fn, type)
         | 
| 174 170 |  | 
| 175 171 | 
             
                def provider_fn(self) -> InjectorProviderFn:
         | 
| 176 172 | 
             
                    def pfn(i: Injector) -> ta.Any:
         | 
| @@ -184,7 +180,7 @@ class CtorInjectorProvider(InjectorProvider): | |
| 184 180 | 
             
                cls_: type
         | 
| 185 181 |  | 
| 186 182 | 
             
                def __post_init__(self) -> None:
         | 
| 187 | 
            -
                     | 
| 183 | 
            +
                    check.isinstance(self.cls_, type)
         | 
| 188 184 |  | 
| 189 185 | 
             
                def provider_fn(self) -> InjectorProviderFn:
         | 
| 190 186 | 
             
                    def pfn(i: Injector) -> ta.Any:
         | 
| @@ -206,7 +202,7 @@ class SingletonInjectorProvider(InjectorProvider): | |
| 206 202 | 
             
                p: InjectorProvider
         | 
| 207 203 |  | 
| 208 204 | 
             
                def __post_init__(self) -> None:
         | 
| 209 | 
            -
                     | 
| 205 | 
            +
                    check.isinstance(self.p, InjectorProvider)
         | 
| 210 206 |  | 
| 211 207 | 
             
                def provider_fn(self) -> InjectorProviderFn:
         | 
| 212 208 | 
             
                    v = not_set = object()
         | 
| @@ -226,7 +222,7 @@ class LinkInjectorProvider(InjectorProvider): | |
| 226 222 | 
             
                k: InjectorKey
         | 
| 227 223 |  | 
| 228 224 | 
             
                def __post_init__(self) -> None:
         | 
| 229 | 
            -
                     | 
| 225 | 
            +
                    check.isinstance(self.k, InjectorKey)
         | 
| 230 226 |  | 
| 231 227 | 
             
                def provider_fn(self) -> InjectorProviderFn:
         | 
| 232 228 | 
             
                    def pfn(i: Injector) -> ta.Any:
         | 
| @@ -423,7 +419,7 @@ def build_injection_kwargs_target( | |
| 423 419 |  | 
| 424 420 | 
             
                skip_names: ta.Set[str] = set()
         | 
| 425 421 | 
             
                if skip_kwargs is not None:
         | 
| 426 | 
            -
                    skip_names.update( | 
| 422 | 
            +
                    skip_names.update(check.not_isinstance(skip_kwargs, str))
         | 
| 427 423 |  | 
| 428 424 | 
             
                seen: ta.Set[InjectorKey] = set()
         | 
| 429 425 | 
             
                kws: ta.List[InjectionKwarg] = []
         | 
| @@ -484,8 +480,8 @@ class _Injector(Injector): | |
| 484 480 | 
             
                def __init__(self, bs: InjectorBindings, p: ta.Optional[Injector] = None) -> None:
         | 
| 485 481 | 
             
                    super().__init__()
         | 
| 486 482 |  | 
| 487 | 
            -
                    self._bs =  | 
| 488 | 
            -
                    self._p: ta.Optional[Injector] =  | 
| 483 | 
            +
                    self._bs = check.isinstance(bs, InjectorBindings)
         | 
| 484 | 
            +
                    self._p: ta.Optional[Injector] = check.isinstance(p, (Injector, type(None)))
         | 
| 489 485 |  | 
| 490 486 | 
             
                    self._pfm = {k: v.provider_fn() for k, v in build_injector_provider_map(bs).items()}
         | 
| 491 487 |  | 
| @@ -516,8 +512,8 @@ class _Injector(Injector): | |
| 516 512 | 
             
                        return Maybe.empty()
         | 
| 517 513 |  | 
| 518 514 | 
             
                    def handle_provision(self, key: InjectorKey, mv: Maybe) -> Maybe:
         | 
| 519 | 
            -
                         | 
| 520 | 
            -
                         | 
| 515 | 
            +
                        check.in_(key, self._seen_keys)
         | 
| 516 | 
            +
                        check.not_in(key, self._provisions)
         | 
| 521 517 | 
             
                        self._provisions[key] = mv
         | 
| 522 518 | 
             
                        return mv
         | 
| 523 519 |  | 
| @@ -631,7 +627,7 @@ class InjectorBinder: | |
| 631 627 |  | 
| 632 628 | 
             
                @classmethod
         | 
| 633 629 | 
             
                def bind_as_fn(cls, icls: ta.Type[T]) -> ta.Type[T]:
         | 
| 634 | 
            -
                     | 
| 630 | 
            +
                    check.isinstance(icls, type)
         | 
| 635 631 | 
             
                    if icls not in cls._FN_TYPES:
         | 
| 636 632 | 
             
                        cls._FN_TYPES = (*cls._FN_TYPES, icls)
         | 
| 637 633 | 
             
                    return icls
         | 
| @@ -688,7 +684,7 @@ class InjectorBinder: | |
| 688 684 | 
             
                        to_fn = obj
         | 
| 689 685 | 
             
                        if key is None:
         | 
| 690 686 | 
             
                            insp = _injection_inspect(obj)
         | 
| 691 | 
            -
                            key_cls: ta.Any = check_valid_injector_key_cls( | 
| 687 | 
            +
                            key_cls: ta.Any = check_valid_injector_key_cls(check.not_none(insp.type_hints.get('return')))
         | 
| 692 688 | 
             
                            key = InjectorKey(key_cls)
         | 
| 693 689 | 
             
                    else:
         | 
| 694 690 | 
             
                        if to_const is not None:
         |