omlish 0.0.0.dev22__tar.gz → 0.0.0.dev23__tar.gz
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-0.0.0.dev22/omlish.egg-info → omlish-0.0.0.dev23}/PKG-INFO +1 -1
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/__about__.py +10 -3
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/asyncs/bridge.py +3 -0
- omlish-0.0.0.dev23/omlish/bootstrap/__init__.py +42 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/bootstrap/base.py +3 -1
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/bootstrap/diag.py +48 -1
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/bootstrap/main.py +2 -1
- omlish-0.0.0.dev23/omlish/bootstrap/marshal.py +18 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/check.py +123 -33
- omlish-0.0.0.dev23/omlish/diag/asts.py +132 -0
- omlish-0.0.0.dev23/omlish/diag/pycharm.py +80 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/docker.py +3 -0
- omlish-0.0.0.dev23/omlish/genmachine.py +58 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/__init__.py +4 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/base64.py +4 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/primitives.py +6 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/standard.py +4 -0
- omlish-0.0.0.dev23/omlish/marshal/unions.py +101 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/matchfns.py +3 -3
- omlish-0.0.0.dev23/omlish/sql/__init__.py +27 -0
- omlish-0.0.0.dev23/omlish/sql/qualifiedname.py +82 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23/omlish.egg-info}/PKG-INFO +1 -1
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish.egg-info/SOURCES.txt +6 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/pyproject.toml +1 -1
- omlish-0.0.0.dev22/omlish/bootstrap/__init__.py +0 -3
- omlish-0.0.0.dev22/omlish/sql/__init__.py +0 -9
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/LICENSE +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/MANIFEST.in +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/README.rst +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/argparse.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/asyncs/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/asyncs/anyio.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/asyncs/asyncio.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/asyncs/asyncs.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/asyncs/flavors.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/asyncs/trio.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/asyncs/trio_asyncio.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/bootstrap/__main__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/bootstrap/harness.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/bootstrap/sys.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/c3.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/cached.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/_abc.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/_io_abc.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/cache/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/cache/descriptor.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/cache/impl.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/cache/types.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/coerce.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/exceptions.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/frozen.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/identity.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/indexed.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/mappings.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/ordered.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/persistent.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/skiplist.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/sorted.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/treap.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/treapmap.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/unmodifiable.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/utils.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/concurrent/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/concurrent/executors.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/concurrent/futures.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/concurrent/threadlets.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/configs/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/configs/classes.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/configs/flattening.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/configs/strings.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/api.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/as_.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/copy.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/descriptors.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/exceptions.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/fields.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/frozen.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/hashing.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/init.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/internals.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/main.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/metaclass.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/metadata.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/order.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/params.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/processing.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/reflect.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/replace.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/repr.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/simple.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/slots.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/utils.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/utils.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/datetimes.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/defs.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/diag/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/diag/procfs.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/diag/procstats.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/diag/ps.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/diag/pydevd.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/diag/replserver/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/diag/replserver/__main__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/diag/replserver/console.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/diag/replserver/server.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/diag/threads.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dispatch/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dispatch/_dispatch2.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dispatch/_dispatch3.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dispatch/dispatch.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dispatch/functions.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dispatch/methods.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dynamic.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/fnpairs.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/formats/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/formats/dotenv.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/formats/json.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/formats/props.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/formats/yaml.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/graphs/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/graphs/dags.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/graphs/domination.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/graphs/dot/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/graphs/dot/items.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/graphs/dot/rendering.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/graphs/dot/utils.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/graphs/trees.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/http/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/http/asgi.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/http/collections.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/http/consts.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/http/cookies.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/http/dates.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/http/encodings.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/http/json.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/http/sessions.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/http/wsgi.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/binder.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/bindings.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/eagers.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/elements.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/exceptions.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/impl/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/impl/bindings.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/impl/elements.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/impl/injector.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/impl/inspect.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/impl/multis.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/impl/origins.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/impl/privates.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/impl/providers.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/impl/proxy.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/impl/scopes.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/injector.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/inspect.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/keys.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/listeners.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/managed.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/multis.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/origins.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/overrides.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/privates.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/providers.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/scopes.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/types.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/utils.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/iterators.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/cached.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/classes/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/classes/abstract.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/classes/restrict.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/classes/simple.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/classes/virtual.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/clsdct.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/cmp.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/contextmanagers.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/descriptors.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/exceptions.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/functions.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/imports.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/iterables.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/maybes.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/objects.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/resolving.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/strings.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/sys.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/timeouts.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/typing.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/libc.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lifecycles/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lifecycles/abstract.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lifecycles/base.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lifecycles/contextmanagers.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lifecycles/controller.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lifecycles/manager.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lifecycles/states.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lifecycles/transitions.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lite/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lite/cached.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lite/check.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lite/contextmanagers.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lite/json.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lite/logs.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lite/marshal.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lite/reflect.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lite/runtime.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lite/secrets.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lite/strings.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lite/subprocesses.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/logs/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/logs/_abc.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/logs/configs.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/logs/formatters.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/logs/handlers.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/logs/noisy.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/logs/utils.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/any.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/base.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/dataclasses.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/datetimes.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/enums.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/exceptions.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/factories.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/forbidden.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/global_.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/helpers.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/iterables.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/mappings.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/maybes.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/naming.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/numbers.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/objects.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/optionals.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/polymorphism.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/registries.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/utils.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/uuids.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/values.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/math.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/multiprocessing.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/os.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/reflect/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/reflect/isinstance.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/reflect/ops.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/reflect/subst.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/reflect/types.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/runmodule.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/secrets/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/secrets/crypto.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/secrets/marshal.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/secrets/openssl.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/secrets/passwords.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/secrets/secrets.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/secrets/subprocesses.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/specs/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/specs/jsonschema/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/specs/jsonschema/keywords/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/specs/jsonschema/keywords/base.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/specs/jsonschema/keywords/core.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/specs/jsonschema/keywords/metadata.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/specs/jsonschema/keywords/parse.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/specs/jsonschema/keywords/render.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/specs/jsonschema/keywords/validation.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/specs/jsonschema/schemas/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/specs/jsonschema/schemas/draft202012/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/specs/jsonschema/schemas/draft202012/vocabularies/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/specs/jsonschema/types.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/sql/_abc.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/sql/asyncs.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/sql/dbs.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/sql/duckdb.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/sql/exprs.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/sql/secrets.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/sql/sqlean.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/stats.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/sync.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/term.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/pytest/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/pytest/helpers.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/pytest/inject/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/pytest/inject/harness.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/pytest/marks.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/pytest/plugins/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/pytest/plugins/_registry.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/pytest/plugins/asyncs.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/pytest/plugins/depskip.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/pytest/plugins/logging.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/pytest/plugins/managermarks.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/pytest/plugins/pydevd.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/pytest/plugins/repeat.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/pytest/plugins/skips.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/pytest/plugins/spacing.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/pytest/plugins/switches.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/pytest/plugins/utils.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/testing.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/text/__init__.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/text/delimit.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/text/glyphsplit.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/text/indent.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/text/parts.py +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish.egg-info/dependency_links.txt +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish.egg-info/requires.txt +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish.egg-info/top_level.txt +0 -0
- {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/setup.cfg +0 -0
@@ -1,5 +1,5 @@
|
|
1
|
-
__version__ = '0.0.0.
|
2
|
-
__revision__ = '
|
1
|
+
__version__ = '0.0.0.dev23'
|
2
|
+
__revision__ = '1d019b6879a9552ea31622e40f50d260d6b08824'
|
3
3
|
|
4
4
|
|
5
5
|
#
|
@@ -80,7 +80,11 @@ class Project(ProjectBase):
|
|
80
80
|
'sqlalchemy[asyncio] ~= 2.0',
|
81
81
|
|
82
82
|
'pg8000 ~= 1.31',
|
83
|
+
# 'psycopg2 ~= 2.9',
|
84
|
+
|
83
85
|
'pymysql ~= 1.1',
|
86
|
+
# 'mysql-connector-python ~= 9.0',
|
87
|
+
# 'mysqlclient ~= 2.2',
|
84
88
|
|
85
89
|
'aiomysql ~= 0.2',
|
86
90
|
'aiosqlite ~= 0.20',
|
@@ -110,7 +114,10 @@ class SetuptoolsBase:
|
|
110
114
|
include_package_data = False
|
111
115
|
|
112
116
|
find_packages = {
|
113
|
-
'exclude': [
|
117
|
+
'exclude': [
|
118
|
+
'*.tests',
|
119
|
+
'*.tests.*',
|
120
|
+
],
|
114
121
|
}
|
115
122
|
|
116
123
|
|
@@ -0,0 +1,42 @@
|
|
1
|
+
from .base import ( # noqa
|
2
|
+
Bootstrap,
|
3
|
+
ContextBootstrap,
|
4
|
+
SimpleBootstrap,
|
5
|
+
)
|
6
|
+
|
7
|
+
from .diag import ( # noqa
|
8
|
+
CheckBootstrap,
|
9
|
+
CprofileBootstrap,
|
10
|
+
PycharmBootstrap,
|
11
|
+
ThreadDumpBootstrap,
|
12
|
+
TimebombBootstrap,
|
13
|
+
)
|
14
|
+
|
15
|
+
from .harness import ( # noqa
|
16
|
+
bootstrap,
|
17
|
+
)
|
18
|
+
|
19
|
+
from .sys import ( # noqa
|
20
|
+
CwdBootstrap,
|
21
|
+
EnvBootstrap,
|
22
|
+
FaulthandlerBootstrap,
|
23
|
+
FdsBootstrap,
|
24
|
+
GcBootstrap,
|
25
|
+
GcDebugFlag,
|
26
|
+
ImportBootstrap,
|
27
|
+
LogBootstrap,
|
28
|
+
NiceBootstrap,
|
29
|
+
PidfileBootstrap,
|
30
|
+
PrctlBootstrap,
|
31
|
+
PrintPidBootstrap,
|
32
|
+
RlimitBootstrap,
|
33
|
+
SetuidBootstrap,
|
34
|
+
)
|
35
|
+
|
36
|
+
|
37
|
+
##
|
38
|
+
|
39
|
+
|
40
|
+
from ..lang.imports import _register_conditional_import # noqa
|
41
|
+
|
42
|
+
_register_conditional_import('..marshal', '.marshal', __package__)
|
@@ -2,6 +2,8 @@ import abc
|
|
2
2
|
import dataclasses as dc
|
3
3
|
import typing as ta
|
4
4
|
|
5
|
+
from omlish import lang
|
6
|
+
|
5
7
|
|
6
8
|
BootstrapConfigT = ta.TypeVar('BootstrapConfigT', bound='Bootstrap.Config')
|
7
9
|
|
@@ -9,7 +11,7 @@ BootstrapConfigT = ta.TypeVar('BootstrapConfigT', bound='Bootstrap.Config')
|
|
9
11
|
##
|
10
12
|
|
11
13
|
|
12
|
-
class Bootstrap(abc.ABC, ta.Generic[BootstrapConfigT]):
|
14
|
+
class Bootstrap(abc.ABC, lang.PackageSealed, ta.Generic[BootstrapConfigT]):
|
13
15
|
@dc.dataclass(frozen=True)
|
14
16
|
class Config(abc.ABC): # noqa
|
15
17
|
pass
|
@@ -5,28 +5,56 @@ import signal
|
|
5
5
|
import sys
|
6
6
|
import typing as ta
|
7
7
|
|
8
|
+
from .. import check
|
8
9
|
from .. import lang
|
9
10
|
from .base import Bootstrap
|
10
11
|
from .base import ContextBootstrap
|
12
|
+
from .base import SimpleBootstrap
|
11
13
|
|
12
14
|
|
13
15
|
if ta.TYPE_CHECKING:
|
14
16
|
import cProfile # noqa
|
15
17
|
import pstats
|
16
18
|
|
19
|
+
from ..diag import pycharm as diagpc
|
17
20
|
from ..diag import threads as diagt
|
18
21
|
|
19
22
|
else:
|
20
23
|
cProfile = lang.proxy_import('cProfile') # noqa
|
21
24
|
pstats = lang.proxy_import('pstats')
|
22
25
|
|
26
|
+
diagpc = lang.proxy_import('..diag.pycharm', __package__)
|
23
27
|
diagt = lang.proxy_import('..diag.threads', __package__)
|
24
28
|
|
25
29
|
|
26
30
|
##
|
27
31
|
|
28
32
|
|
29
|
-
class
|
33
|
+
class CheckBootstrap(ContextBootstrap['CheckBootstrap.Config']):
|
34
|
+
@dc.dataclass(frozen=True)
|
35
|
+
class Config(Bootstrap.Config):
|
36
|
+
breakpoint: bool = False
|
37
|
+
|
38
|
+
@staticmethod
|
39
|
+
def _breakpoint(exc: Exception) -> None: # noqa
|
40
|
+
breakpoint() # noqa
|
41
|
+
|
42
|
+
@contextlib.contextmanager
|
43
|
+
def enter(self) -> ta.Iterator[None]:
|
44
|
+
if not self._config.breakpoint:
|
45
|
+
return
|
46
|
+
|
47
|
+
check.register_on_raise(CheckBootstrap._breakpoint)
|
48
|
+
try:
|
49
|
+
yield
|
50
|
+
finally:
|
51
|
+
check.unregister_on_raise(CheckBootstrap._breakpoint)
|
52
|
+
|
53
|
+
|
54
|
+
##
|
55
|
+
|
56
|
+
|
57
|
+
class CprofileBootstrap(ContextBootstrap['CprofileBootstrap.Config']):
|
30
58
|
@dc.dataclass(frozen=True)
|
31
59
|
class Config(Bootstrap.Config):
|
32
60
|
enable: bool = False
|
@@ -128,3 +156,22 @@ class TimebombBootstrap(ContextBootstrap['TimebombBootstrap.Config']):
|
|
128
156
|
yield
|
129
157
|
finally:
|
130
158
|
tbt.stop_nowait()
|
159
|
+
|
160
|
+
|
161
|
+
##
|
162
|
+
|
163
|
+
|
164
|
+
class PycharmBootstrap(SimpleBootstrap['PycharmBootstrap.Config']):
|
165
|
+
@dc.dataclass(frozen=True)
|
166
|
+
class Config(Bootstrap.Config):
|
167
|
+
debug_host: ta.Optional[str] = None
|
168
|
+
debug_port: ta.Optional[int] = None
|
169
|
+
debug_version: ta.Optional[str] = None
|
170
|
+
|
171
|
+
def run(self) -> None:
|
172
|
+
if self._config.debug_port is not None:
|
173
|
+
diagpc.pycharm_remote_debugger_attach(
|
174
|
+
self._config.debug_host,
|
175
|
+
self._config.debug_port,
|
176
|
+
version=self._config.debug_version,
|
177
|
+
)
|
@@ -156,8 +156,9 @@ def _main() -> int:
|
|
156
156
|
with bootstrap(*cfgs):
|
157
157
|
tgt = args.target
|
158
158
|
|
159
|
+
sys.argv = [tgt, *(args.args or ())]
|
160
|
+
|
159
161
|
if args.module:
|
160
|
-
sys.argv = [tgt, *(args.args or ())]
|
161
162
|
runpy._run_module_as_main(tgt) # type: ignore # noqa
|
162
163
|
|
163
164
|
else:
|
@@ -0,0 +1,18 @@
|
|
1
|
+
from .. import lang
|
2
|
+
from .. import marshal as msh
|
3
|
+
from .base import Bootstrap
|
4
|
+
from .harness import BOOTSTRAP_TYPES_BY_NAME
|
5
|
+
|
6
|
+
|
7
|
+
@lang.cached_function
|
8
|
+
def _install_standard_marshalling() -> None:
|
9
|
+
cfgs_poly = msh.Polymorphism(
|
10
|
+
Bootstrap.Config,
|
11
|
+
[msh.Impl(b.Config, n) for n, b in BOOTSTRAP_TYPES_BY_NAME.items()],
|
12
|
+
)
|
13
|
+
|
14
|
+
msh.STANDARD_MARSHALER_FACTORIES[0:0] = [msh.PolymorphismMarshalerFactory(cfgs_poly)]
|
15
|
+
msh.STANDARD_UNMARSHALER_FACTORIES[0:0] = [msh.PolymorphismUnmarshalerFactory(cfgs_poly)]
|
16
|
+
|
17
|
+
|
18
|
+
_install_standard_marshalling()
|
@@ -3,6 +3,7 @@ TODO:
|
|
3
3
|
- def maybe(v: lang.Maybe[T])
|
4
4
|
"""
|
5
5
|
import collections
|
6
|
+
import threading
|
6
7
|
import typing as ta
|
7
8
|
|
8
9
|
|
@@ -21,6 +22,62 @@ _callable = callable
|
|
21
22
|
##
|
22
23
|
|
23
24
|
|
25
|
+
_CONFIG_LOCK = threading.RLock()
|
26
|
+
|
27
|
+
|
28
|
+
OnRaiseFn: ta.TypeAlias = ta.Callable[[Exception], None]
|
29
|
+
_ON_RAISE: ta.Sequence[OnRaiseFn] = []
|
30
|
+
|
31
|
+
|
32
|
+
def register_on_raise(fn: OnRaiseFn) -> None:
|
33
|
+
global _ON_RAISE
|
34
|
+
with _CONFIG_LOCK:
|
35
|
+
_ON_RAISE = [*_ON_RAISE, fn]
|
36
|
+
|
37
|
+
|
38
|
+
def unregister_on_raise(fn: OnRaiseFn) -> None:
|
39
|
+
global _ON_RAISE
|
40
|
+
with _CONFIG_LOCK:
|
41
|
+
_ON_RAISE = [e for e in _ON_RAISE if e != fn]
|
42
|
+
|
43
|
+
|
44
|
+
#
|
45
|
+
|
46
|
+
|
47
|
+
_render_args: ta.Callable[..., str | None] | None = None
|
48
|
+
|
49
|
+
|
50
|
+
def enable_args_rendering() -> bool:
|
51
|
+
global _render_args
|
52
|
+
if _render_args is not None:
|
53
|
+
return True
|
54
|
+
|
55
|
+
with _CONFIG_LOCK:
|
56
|
+
if _render_args is not None:
|
57
|
+
return True # type: ignore
|
58
|
+
|
59
|
+
try:
|
60
|
+
from .diag.asts import ArgsRenderer
|
61
|
+
|
62
|
+
ArgsRenderer.smoketest()
|
63
|
+
|
64
|
+
except Exception: # noqa
|
65
|
+
return False
|
66
|
+
|
67
|
+
def _real_render_args(fmt: str, *args: ta.Any) -> str | None:
|
68
|
+
ra = ArgsRenderer(back=3).render_args(*args)
|
69
|
+
if ra is None:
|
70
|
+
return None
|
71
|
+
|
72
|
+
return fmt % tuple(str(a) for a in ra)
|
73
|
+
|
74
|
+
_render_args = _real_render_args
|
75
|
+
return True
|
76
|
+
|
77
|
+
|
78
|
+
#
|
79
|
+
|
80
|
+
|
24
81
|
def _default_exception_factory(exc_cls: type[Exception], *args, **kwargs) -> Exception:
|
25
82
|
return exc_cls(*args, **kwargs) # noqa
|
26
83
|
|
@@ -28,20 +85,45 @@ def _default_exception_factory(exc_cls: type[Exception], *args, **kwargs) -> Exc
|
|
28
85
|
_EXCEPTION_FACTORY = _default_exception_factory
|
29
86
|
|
30
87
|
|
88
|
+
class _Args:
|
89
|
+
def __init__(self, *args, **kwargs):
|
90
|
+
self.args = args
|
91
|
+
self.kwargs = kwargs
|
92
|
+
|
93
|
+
|
31
94
|
def _raise(
|
32
95
|
exception_type: type[Exception],
|
33
96
|
default_message: str,
|
34
97
|
message: Message,
|
35
|
-
|
36
|
-
|
98
|
+
ak: _Args = _Args(),
|
99
|
+
*,
|
100
|
+
render_fmt: str | None = None,
|
37
101
|
) -> ta.NoReturn:
|
102
|
+
exc_args = ()
|
38
103
|
if _callable(message):
|
39
|
-
message = ta.cast(ta.Callable, message)(*args, **kwargs)
|
104
|
+
message = ta.cast(ta.Callable, message)(*ak.args, **ak.kwargs)
|
40
105
|
if _isinstance(message, tuple):
|
41
|
-
message, *
|
106
|
+
message, *exc_args = message # type: ignore
|
107
|
+
|
42
108
|
if message is None:
|
43
109
|
message = default_message
|
44
|
-
|
110
|
+
|
111
|
+
if render_fmt is not None and _render_args is not None:
|
112
|
+
rendered_args = _render_args(render_fmt, *ak.args)
|
113
|
+
if rendered_args is not None:
|
114
|
+
message = f'{message} : {rendered_args}'
|
115
|
+
|
116
|
+
exc = _EXCEPTION_FACTORY(
|
117
|
+
exception_type,
|
118
|
+
message,
|
119
|
+
*exc_args,
|
120
|
+
*ak.args,
|
121
|
+
**ak.kwargs,
|
122
|
+
)
|
123
|
+
|
124
|
+
for fn in _ON_RAISE:
|
125
|
+
fn(exc)
|
126
|
+
|
45
127
|
raise exc
|
46
128
|
|
47
129
|
|
@@ -60,7 +142,7 @@ def _unpack_isinstance_spec(spec: ta.Any) -> tuple:
|
|
60
142
|
|
61
143
|
def isinstance(v: ta.Any, spec: type[T] | tuple, msg: Message = None) -> T: # noqa
|
62
144
|
if not _isinstance(v, _unpack_isinstance_spec(spec)):
|
63
|
-
_raise(TypeError, 'Must be instance', msg, v, spec)
|
145
|
+
_raise(TypeError, 'Must be instance', msg, _Args(v, spec))
|
64
146
|
return v
|
65
147
|
|
66
148
|
|
@@ -73,7 +155,7 @@ def of_isinstance(spec: type[T] | tuple, msg: Message = None) -> ta.Callable[[ta
|
|
73
155
|
|
74
156
|
def cast(v: ta.Any, cls: type[T], msg: Message = None) -> T: # noqa
|
75
157
|
if not _isinstance(v, cls):
|
76
|
-
_raise(TypeError, 'Must be instance', msg, v, cls)
|
158
|
+
_raise(TypeError, 'Must be instance', msg, _Args(v, cls))
|
77
159
|
return v
|
78
160
|
|
79
161
|
|
@@ -86,7 +168,7 @@ def of_cast(cls: type[T], msg: Message = None) -> ta.Callable[[T], T]:
|
|
86
168
|
|
87
169
|
def not_isinstance(v: T, spec: ta.Any, msg: Message = None) -> T: # noqa
|
88
170
|
if _isinstance(v, _unpack_isinstance_spec(spec)):
|
89
|
-
_raise(TypeError, 'Must not be instance', msg, v, spec)
|
171
|
+
_raise(TypeError, 'Must not be instance', msg, _Args(v, spec))
|
90
172
|
return v
|
91
173
|
|
92
174
|
|
@@ -102,13 +184,13 @@ def of_not_isinstance(spec: ta.Any, msg: Message = None) -> ta.Callable[[T], T]:
|
|
102
184
|
|
103
185
|
def issubclass(v: type[T], spec: ta.Any, msg: Message = None) -> type[T]: # noqa
|
104
186
|
if not _issubclass(v, spec):
|
105
|
-
_raise(TypeError, 'Must be subclass', msg, v, spec)
|
187
|
+
_raise(TypeError, 'Must be subclass', msg, _Args(v, spec))
|
106
188
|
return v
|
107
189
|
|
108
190
|
|
109
191
|
def not_issubclass(v: type[T], spec: ta.Any, msg: Message = None) -> type[T]: # noqa
|
110
192
|
if _issubclass(v, spec):
|
111
|
-
_raise(TypeError, 'Must not be subclass', msg, v, spec)
|
193
|
+
_raise(TypeError, 'Must not be subclass', msg, _Args(v, spec))
|
112
194
|
return v
|
113
195
|
|
114
196
|
|
@@ -117,32 +199,43 @@ def not_issubclass(v: type[T], spec: ta.Any, msg: Message = None) -> type[T]: #
|
|
117
199
|
|
118
200
|
def in_(v: T, c: ta.Container[T], msg: Message = None) -> T:
|
119
201
|
if v not in c:
|
120
|
-
_raise(ValueError, 'Must be in', msg, v, c)
|
202
|
+
_raise(ValueError, 'Must be in', msg, _Args(v, c))
|
121
203
|
return v
|
122
204
|
|
123
205
|
|
124
206
|
def not_in(v: T, c: ta.Container[T], msg: Message = None) -> T:
|
125
207
|
if v in c:
|
126
|
-
_raise(ValueError, 'Must not be in', msg, v, c)
|
208
|
+
_raise(ValueError, 'Must not be in', msg, _Args(v, c))
|
127
209
|
return v
|
128
210
|
|
129
211
|
|
130
212
|
def empty(v: SizedT, msg: Message = None) -> SizedT:
|
131
213
|
if len(v) != 0:
|
132
|
-
_raise(ValueError, 'Must be empty', msg, v)
|
214
|
+
_raise(ValueError, 'Must be empty', msg, _Args(v))
|
215
|
+
return v
|
216
|
+
|
217
|
+
|
218
|
+
def iterempty(v: ta.Iterable[T], msg: Message = None) -> ta.Iterable[T]:
|
219
|
+
it = iter(v)
|
220
|
+
try:
|
221
|
+
next(it)
|
222
|
+
except StopIteration:
|
223
|
+
pass
|
224
|
+
else:
|
225
|
+
_raise(ValueError, 'Must be empty', msg, _Args(v))
|
133
226
|
return v
|
134
227
|
|
135
228
|
|
136
229
|
def not_empty(v: SizedT, msg: Message = None) -> SizedT:
|
137
230
|
if len(v) == 0:
|
138
|
-
_raise(ValueError, 'Must not be empty', msg, v)
|
231
|
+
_raise(ValueError, 'Must not be empty', msg, _Args(v))
|
139
232
|
return v
|
140
233
|
|
141
234
|
|
142
235
|
def unique(it: ta.Iterable[T], msg: Message = None) -> ta.Iterable[T]:
|
143
236
|
dupes = [e for e, c in collections.Counter(it).items() if c > 1]
|
144
237
|
if dupes:
|
145
|
-
_raise(ValueError, 'Must be unique', msg, it, dupes)
|
238
|
+
_raise(ValueError, 'Must be unique', msg, _Args(it, dupes))
|
146
239
|
return it
|
147
240
|
|
148
241
|
|
@@ -150,7 +243,7 @@ def single(obj: ta.Iterable[T], message: Message = None) -> T:
|
|
150
243
|
try:
|
151
244
|
[value] = obj
|
152
245
|
except ValueError:
|
153
|
-
_raise(ValueError, 'Must be single', message, obj)
|
246
|
+
_raise(ValueError, 'Must be single', message, _Args(obj))
|
154
247
|
else:
|
155
248
|
return value
|
156
249
|
|
@@ -165,7 +258,7 @@ def optional_single(obj: ta.Iterable[T], message: Message = None) -> T | None:
|
|
165
258
|
next(it)
|
166
259
|
except StopIteration:
|
167
260
|
return value # noqa
|
168
|
-
_raise(ValueError, 'Must be empty or single', message, obj)
|
261
|
+
_raise(ValueError, 'Must be empty or single', message, _Args(obj))
|
169
262
|
|
170
263
|
|
171
264
|
##
|
@@ -173,48 +266,45 @@ def optional_single(obj: ta.Iterable[T], message: Message = None) -> T | None:
|
|
173
266
|
|
174
267
|
def none(v: ta.Any, msg: Message = None) -> None:
|
175
268
|
if v is not None:
|
176
|
-
_raise(ValueError, 'Must be None', msg, v)
|
269
|
+
_raise(ValueError, 'Must be None', msg, _Args(v))
|
177
270
|
|
178
271
|
|
179
272
|
def not_none(v: T | None, msg: Message = None) -> T:
|
180
273
|
if v is None:
|
181
|
-
_raise(ValueError, 'Must not be None', msg, v)
|
274
|
+
_raise(ValueError, 'Must not be None', msg, _Args(v))
|
182
275
|
return v
|
183
276
|
|
184
277
|
|
185
278
|
##
|
186
279
|
|
187
280
|
|
188
|
-
def equal(v: T,
|
189
|
-
|
190
|
-
|
191
|
-
_raise(ValueError, 'Must be equal', msg, v, os)
|
281
|
+
def equal(v: T, o: ta.Any, msg: Message = None) -> T:
|
282
|
+
if o != v:
|
283
|
+
_raise(ValueError, 'Must be equal', msg, _Args(v, o), render_fmt='%s != %s')
|
192
284
|
return v
|
193
285
|
|
194
286
|
|
195
|
-
def is_(v: T,
|
196
|
-
|
197
|
-
|
198
|
-
_raise(ValueError, 'Must be the same', msg, v, os)
|
287
|
+
def is_(v: T, o: ta.Any, msg: Message = None) -> T:
|
288
|
+
if o is not v:
|
289
|
+
_raise(ValueError, 'Must be the same', msg, _Args(v, o), render_fmt='%s is not %s')
|
199
290
|
return v
|
200
291
|
|
201
292
|
|
202
|
-
def is_not(v: T,
|
203
|
-
|
204
|
-
|
205
|
-
_raise(ValueError, 'Must not be the same', msg, v, os)
|
293
|
+
def is_not(v: T, o: ta.Any, msg: Message = None) -> T:
|
294
|
+
if o is v:
|
295
|
+
_raise(ValueError, 'Must not be the same', msg, _Args(v, o), render_fmt='%s is %s')
|
206
296
|
return v
|
207
297
|
|
208
298
|
|
209
299
|
def callable(v: T, msg: Message = None) -> T: # noqa
|
210
300
|
if not _callable(v):
|
211
|
-
_raise(TypeError, 'Must be callable', msg, v)
|
301
|
+
_raise(TypeError, 'Must be callable', msg, _Args(v))
|
212
302
|
return v # type: ignore
|
213
303
|
|
214
304
|
|
215
305
|
def non_empty_str(v: str | None, msg: Message = None) -> str:
|
216
306
|
if not _isinstance(v, str) or not v:
|
217
|
-
_raise(ValueError, 'Must be non-empty str', msg, v)
|
307
|
+
_raise(ValueError, 'Must be non-empty str', msg, _Args(v))
|
218
308
|
return v
|
219
309
|
|
220
310
|
|
@@ -0,0 +1,132 @@
|
|
1
|
+
import ast
|
2
|
+
import dataclasses as dc
|
3
|
+
import inspect
|
4
|
+
import pprint
|
5
|
+
import textwrap
|
6
|
+
import types
|
7
|
+
import typing as ta
|
8
|
+
|
9
|
+
from .. import lang
|
10
|
+
|
11
|
+
|
12
|
+
if ta.TYPE_CHECKING:
|
13
|
+
import executing
|
14
|
+
else:
|
15
|
+
executing = lang.proxy_import('executing')
|
16
|
+
|
17
|
+
|
18
|
+
class ArgsRenderer:
|
19
|
+
"""
|
20
|
+
TODO:
|
21
|
+
- kwargs
|
22
|
+
- recursion
|
23
|
+
- whatever pytest looks like
|
24
|
+
- make sure not leaking sensitive data
|
25
|
+
"""
|
26
|
+
|
27
|
+
def __init__(
|
28
|
+
self,
|
29
|
+
origin: types.TracebackType | types.FrameType | None = None,
|
30
|
+
back: int = 1,
|
31
|
+
) -> None:
|
32
|
+
super().__init__()
|
33
|
+
|
34
|
+
self._origin = origin
|
35
|
+
|
36
|
+
self._frame: types.FrameType | None
|
37
|
+
if isinstance(origin, types.TracebackType):
|
38
|
+
self._frame = origin.tb_frame
|
39
|
+
elif isinstance(origin, types.FrameType):
|
40
|
+
self._frame = origin
|
41
|
+
elif origin is None:
|
42
|
+
frame = inspect.currentframe()
|
43
|
+
for _ in range(back + 1):
|
44
|
+
if frame is None:
|
45
|
+
break
|
46
|
+
frame = frame.f_back
|
47
|
+
self._frame = frame
|
48
|
+
else:
|
49
|
+
raise TypeError(origin)
|
50
|
+
|
51
|
+
def _get_indented_text(
|
52
|
+
self,
|
53
|
+
src: executing.Source,
|
54
|
+
node: ast.AST,
|
55
|
+
) -> str:
|
56
|
+
result = src.asttokens().get_text(node)
|
57
|
+
if '\n' in result:
|
58
|
+
result = ' ' * node.first_token.start[1] + result # type: ignore
|
59
|
+
result = textwrap.dedent(result)
|
60
|
+
result = result.strip()
|
61
|
+
return result
|
62
|
+
|
63
|
+
def _val_to_string(self, obj: ta.Any) -> str:
|
64
|
+
s = pprint.pformat(obj)
|
65
|
+
s = s.replace('\\n', '\n')
|
66
|
+
return s
|
67
|
+
|
68
|
+
def _is_literal_expr(self, s: str) -> bool:
|
69
|
+
try:
|
70
|
+
ast.literal_eval(s)
|
71
|
+
except Exception: # noqa
|
72
|
+
return False
|
73
|
+
return True
|
74
|
+
|
75
|
+
@dc.dataclass(frozen=True)
|
76
|
+
class RenderedArg:
|
77
|
+
val: str
|
78
|
+
expr: str
|
79
|
+
is_literal_expr: bool
|
80
|
+
|
81
|
+
def __str__(self) -> str:
|
82
|
+
if self.is_literal_expr:
|
83
|
+
return self.val
|
84
|
+
else:
|
85
|
+
return f'({self.expr} = {self.val})'
|
86
|
+
|
87
|
+
def render_args(
|
88
|
+
self,
|
89
|
+
*vals: ta.Any,
|
90
|
+
) -> ta.Sequence[RenderedArg] | None:
|
91
|
+
if self._frame is None:
|
92
|
+
return None
|
93
|
+
|
94
|
+
call_node = executing.Source.executing(self._frame).node
|
95
|
+
if not isinstance(call_node, ast.Call):
|
96
|
+
return None
|
97
|
+
|
98
|
+
source = executing.Source.for_frame(self._frame)
|
99
|
+
|
100
|
+
exprs = [
|
101
|
+
self._get_indented_text(source, arg) # noqa
|
102
|
+
for arg in call_node.args
|
103
|
+
]
|
104
|
+
if len(exprs) != len(vals):
|
105
|
+
return None
|
106
|
+
|
107
|
+
return [
|
108
|
+
self.RenderedArg(
|
109
|
+
val=self._val_to_string(val),
|
110
|
+
expr=expr,
|
111
|
+
is_literal_expr=self._is_literal_expr(expr),
|
112
|
+
)
|
113
|
+
for val, expr in zip(vals, exprs)
|
114
|
+
]
|
115
|
+
|
116
|
+
@classmethod
|
117
|
+
def smoketest(cls) -> bool:
|
118
|
+
def bar(z):
|
119
|
+
return z + 1
|
120
|
+
|
121
|
+
def foo(x, y):
|
122
|
+
return cls().render_args(x, y)
|
123
|
+
|
124
|
+
r = foo(1, bar(2))
|
125
|
+
if r is None:
|
126
|
+
return False
|
127
|
+
|
128
|
+
x, y = r
|
129
|
+
return (
|
130
|
+
x == cls.RenderedArg(val='1', expr='1', is_literal_expr=True) and
|
131
|
+
y == cls.RenderedArg(val='3', expr='bar(2)', is_literal_expr=False)
|
132
|
+
)
|