omlish 0.0.0.dev17__tar.gz → 0.0.0.dev19__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.dev17/omlish.egg-info → omlish-0.0.0.dev19}/PKG-INFO +1 -1
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/__about__.py +2 -2
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/asyncs/anyio.py +22 -12
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/asyncs/flavors.py +4 -2
- omlish-0.0.0.dev19/omlish/bootstrap/__init__.py +3 -0
- omlish-0.0.0.dev19/omlish/bootstrap/__main__.py +4 -0
- omlish-0.0.0.dev19/omlish/bootstrap/base.py +38 -0
- omlish-0.0.0.dev19/omlish/bootstrap/diag.py +128 -0
- omlish-0.0.0.dev19/omlish/bootstrap/harness.py +81 -0
- omlish-0.0.0.dev19/omlish/bootstrap/main.py +183 -0
- omlish-0.0.0.dev19/omlish/bootstrap/sys.py +361 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/defs.py +29 -5
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lite/logs.py +1 -1
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/logs/configs.py +11 -23
- omlish-0.0.0.dev19/omlish/logs/noisy.py +15 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/multiprocessing.py +7 -3
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/testing/pytest/plugins/__init__.py +8 -3
- omlish-0.0.0.dev19/omlish/testing/pytest/plugins/depskip.py +81 -0
- omlish-0.0.0.dev19/omlish/testing/pytest/plugins/utils.py +14 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19/omlish.egg-info}/PKG-INFO +1 -1
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish.egg-info/SOURCES.txt +10 -1
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/pyproject.toml +1 -1
- omlish-0.0.0.dev17/omlish/bootstrap.py +0 -746
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/LICENSE +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/MANIFEST.in +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/README.rst +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/__init__.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/argparse.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/asyncs/__init__.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/asyncs/asyncio.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/asyncs/asyncs.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/asyncs/bridge.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/asyncs/trio.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/asyncs/trio_asyncio.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/c3.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/cached.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/check.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/__init__.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/_abc.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/_io_abc.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/cache/__init__.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/cache/descriptor.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/cache/impl.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/cache/types.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/coerce.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/exceptions.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/frozen.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/identity.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/indexed.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/mappings.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/ordered.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/persistent.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/skiplist.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/sorted.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/treap.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/treapmap.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/unmodifiable.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/utils.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/concurrent.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/configs/__init__.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/configs/classes.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/configs/flattening.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/configs/strings.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/__init__.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/__init__.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/api.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/as_.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/copy.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/descriptors.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/exceptions.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/fields.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/frozen.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/hashing.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/init.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/internals.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/main.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/metaclass.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/metadata.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/order.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/params.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/processing.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/reflect.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/replace.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/repr.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/simple.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/slots.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/utils.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/utils.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/datetimes.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/diag/__init__.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/diag/procfs.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/diag/procstats.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/diag/ps.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/diag/pydevd.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/diag/replserver/__init__.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/diag/replserver/__main__.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/diag/replserver/console.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/diag/replserver/server.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/diag/threads.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dispatch/__init__.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dispatch/_dispatch2.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dispatch/_dispatch3.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dispatch/dispatch.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dispatch/functions.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dispatch/methods.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/docker.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dynamic.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/fnpairs.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/formats/__init__.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/formats/dotenv.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/formats/json.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/formats/props.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/formats/yaml.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/graphs/__init__.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/graphs/dags.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/graphs/domination.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/graphs/dot/__init__.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/graphs/dot/items.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/graphs/dot/rendering.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/graphs/dot/utils.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/graphs/trees.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/http/__init__.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/http/asgi.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/http/collections.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/http/consts.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/http/cookies.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/http/dates.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/http/encodings.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/http/json.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/http/sessions.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/http/wsgi.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/__init__.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/binder.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/bindings.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/eagers.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/elements.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/exceptions.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/impl/__init__.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/impl/bindings.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/impl/elements.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/impl/injector.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/impl/inspect.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/impl/multis.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/impl/origins.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/impl/privates.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/impl/providers.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/impl/proxy.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/impl/scopes.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/injector.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/inspect.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/keys.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/listeners.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/managed.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/multis.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/origins.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/overrides.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/privates.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/providers.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/scopes.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/types.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/utils.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/iterators.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/__init__.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/cached.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/classes/__init__.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/classes/abstract.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/classes/restrict.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/classes/simple.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/classes/virtual.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/clsdct.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/cmp.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/contextmanagers.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/descriptors.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/exceptions.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/functions.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/imports.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/iterables.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/maybes.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/objects.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/resolving.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/strings.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/sys.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/timeouts.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/typing.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/libc.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lifecycles/__init__.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lifecycles/abstract.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lifecycles/base.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lifecycles/contextmanagers.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lifecycles/controller.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lifecycles/manager.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lifecycles/states.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lifecycles/transitions.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lite/__init__.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lite/cached.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lite/check.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lite/contextmanagers.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lite/json.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lite/marshal.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lite/reflect.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lite/runtime.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lite/secrets.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lite/strings.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lite/subprocesses.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/logs/__init__.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/logs/_abc.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/logs/formatters.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/logs/utils.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/__init__.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/any.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/base.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/base64.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/dataclasses.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/datetimes.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/enums.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/exceptions.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/factories.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/forbidden.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/global_.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/iterables.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/mappings.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/maybes.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/naming.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/numbers.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/objects.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/optionals.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/polymorphism.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/primitives.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/registries.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/standard.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/utils.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/uuids.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/values.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/matchfns.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/math.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/os.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/reflect/__init__.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/reflect/isinstance.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/reflect/ops.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/reflect/subst.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/reflect/types.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/runmodule.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/secrets/__init__.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/secrets/crypto.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/secrets/marshal.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/secrets/openssl.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/secrets/passwords.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/secrets/secrets.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/secrets/subprocesses.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/sql/__init__.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/sql/_abc.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/sql/asyncs.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/sql/dbs.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/sql/duckdb.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/sql/exprs.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/sql/secrets.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/sql/sqlean.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/stats.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/sync.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/term.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/testing/__init__.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/testing/pytest/__init__.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/testing/pytest/helpers.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/testing/pytest/inject/__init__.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/testing/pytest/inject/harness.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/testing/pytest/marks.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/testing/pytest/plugins/_registry.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/testing/pytest/plugins/asyncs.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/testing/pytest/plugins/logging.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/testing/pytest/plugins/managermarks.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/testing/pytest/plugins/pydevd.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/testing/pytest/plugins/repeat.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/testing/pytest/plugins/skips.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/testing/pytest/plugins/spacing.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/testing/pytest/plugins/switches.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/testing/testing.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/text/__init__.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/text/delimit.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/text/glyphsplit.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/text/indent.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/text/parts.py +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish.egg-info/dependency_links.txt +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish.egg-info/requires.txt +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish.egg-info/top_level.txt +0 -0
- {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/setup.cfg +0 -0
@@ -37,6 +37,12 @@ from .. import lang
|
|
37
37
|
|
38
38
|
T = ta.TypeVar('T')
|
39
39
|
|
40
|
+
MemoryObjectReceiveStream: ta.TypeAlias = anyio.streams.memory.MemoryObjectReceiveStream
|
41
|
+
MemoryObjectSendStream: ta.TypeAlias = anyio.streams.memory.MemoryObjectSendStream
|
42
|
+
|
43
|
+
StapledByteStream: ta.TypeAlias = anyio.streams.stapled.StapledByteStream
|
44
|
+
StapledObjectStream: ta.TypeAlias = anyio.streams.stapled.StapledObjectStream
|
45
|
+
|
40
46
|
|
41
47
|
##
|
42
48
|
|
@@ -130,39 +136,43 @@ def get_current_backend_task() -> BackendTask | None:
|
|
130
136
|
def split_memory_object_streams(
|
131
137
|
*args: anyio.create_memory_object_stream[T],
|
132
138
|
) -> tuple[
|
133
|
-
|
134
|
-
|
139
|
+
MemoryObjectSendStream[T],
|
140
|
+
MemoryObjectReceiveStream[T],
|
135
141
|
]:
|
136
142
|
[tup] = args
|
137
143
|
return tup
|
138
144
|
|
139
145
|
|
146
|
+
def create_stapled_memory_object_stream(max_buffer_size: float = 0) -> StapledObjectStream:
|
147
|
+
return StapledObjectStream(*anyio.create_memory_object_stream(max_buffer_size))
|
148
|
+
|
149
|
+
|
140
150
|
# FIXME: https://github.com/python/mypy/issues/15238
|
141
151
|
# FIXME: https://youtrack.jetbrains.com/issues?q=tag:%20%7BPEP%20695%7D
|
142
152
|
def create_memory_object_stream[T](max_buffer_size: float = 0) -> tuple[
|
143
|
-
|
144
|
-
|
153
|
+
MemoryObjectSendStream[T],
|
154
|
+
MemoryObjectReceiveStream[T],
|
145
155
|
]:
|
146
156
|
return anyio.create_memory_object_stream[T](max_buffer_size) # noqa
|
147
157
|
|
148
158
|
|
149
159
|
def staple_memory_object_stream(
|
150
160
|
*args: anyio.create_memory_object_stream[T],
|
151
|
-
) ->
|
161
|
+
) -> StapledObjectStream[T]:
|
152
162
|
send, receive = args
|
153
|
-
return
|
154
|
-
check.isinstance(send,
|
155
|
-
check.isinstance(receive,
|
163
|
+
return StapledObjectStream(
|
164
|
+
check.isinstance(send, MemoryObjectSendStream), # type: ignore
|
165
|
+
check.isinstance(receive, MemoryObjectReceiveStream), # type: ignore
|
156
166
|
)
|
157
167
|
|
158
168
|
|
159
169
|
# FIXME: https://github.com/python/mypy/issues/15238
|
160
170
|
# FIXME: https://youtrack.jetbrains.com/issues?q=tag:%20%7BPEP%20695%7D
|
161
|
-
def staple_memory_object_stream2[T](max_buffer_size: float = 0) ->
|
171
|
+
def staple_memory_object_stream2[T](max_buffer_size: float = 0) -> StapledObjectStream[T]:
|
162
172
|
send, receive = anyio.create_memory_object_stream[T](max_buffer_size)
|
163
|
-
return
|
164
|
-
check.isinstance(send,
|
165
|
-
check.isinstance(receive,
|
173
|
+
return StapledObjectStream(
|
174
|
+
check.isinstance(send, MemoryObjectSendStream), # type: ignore
|
175
|
+
check.isinstance(receive, MemoryObjectReceiveStream), # type: ignore
|
166
176
|
)
|
167
177
|
|
168
178
|
|
@@ -1,8 +1,8 @@
|
|
1
1
|
"""
|
2
|
+
Tools for working with the different async loop implementations - currently anyio, asyncio, trio.
|
3
|
+
|
2
4
|
TODO:
|
3
|
-
- 'get current'? -> sniffio..
|
4
5
|
- mark whole class / module?
|
5
|
-
- sync/greenlet bridge
|
6
6
|
"""
|
7
7
|
import abc
|
8
8
|
import dataclasses as dc
|
@@ -73,11 +73,13 @@ def _get_module_flavor(p: str) -> Flavor | None:
|
|
73
73
|
return _MODULE_FLAVOR_CACHE[p]
|
74
74
|
except KeyError:
|
75
75
|
pass
|
76
|
+
|
76
77
|
pf: Flavor | None = None
|
77
78
|
for cp, cf in PACKAGE_FLAVORS.items():
|
78
79
|
if p.startswith(cp) and (len(cp) == len(p) or p[len(cp)] == '.'):
|
79
80
|
pf = cf
|
80
81
|
break
|
82
|
+
|
81
83
|
_MODULE_FLAVOR_CACHE[p] = pf
|
82
84
|
return pf
|
83
85
|
|
@@ -0,0 +1,38 @@
|
|
1
|
+
import abc
|
2
|
+
import dataclasses as dc
|
3
|
+
import typing as ta
|
4
|
+
|
5
|
+
|
6
|
+
BootstrapConfigT = ta.TypeVar('BootstrapConfigT', bound='Bootstrap.Config')
|
7
|
+
|
8
|
+
|
9
|
+
##
|
10
|
+
|
11
|
+
|
12
|
+
class Bootstrap(abc.ABC, ta.Generic[BootstrapConfigT]):
|
13
|
+
@dc.dataclass(frozen=True)
|
14
|
+
class Config(abc.ABC): # noqa
|
15
|
+
pass
|
16
|
+
|
17
|
+
def __init__(self, config: BootstrapConfigT) -> None:
|
18
|
+
super().__init__()
|
19
|
+
self._config = config
|
20
|
+
|
21
|
+
def __init_subclass__(cls, **kwargs: ta.Any) -> None:
|
22
|
+
super().__init_subclass__(**kwargs)
|
23
|
+
if not cls.__name__.endswith('Bootstrap'):
|
24
|
+
raise NameError(cls)
|
25
|
+
if abc.ABC not in cls.__bases__ and not issubclass(cls.__dict__['Config'], Bootstrap.Config):
|
26
|
+
raise TypeError(cls)
|
27
|
+
|
28
|
+
|
29
|
+
class SimpleBootstrap(Bootstrap[BootstrapConfigT], abc.ABC):
|
30
|
+
@abc.abstractmethod
|
31
|
+
def run(self) -> None:
|
32
|
+
raise NotImplementedError
|
33
|
+
|
34
|
+
|
35
|
+
class ContextBootstrap(Bootstrap[BootstrapConfigT], abc.ABC):
|
36
|
+
@abc.abstractmethod
|
37
|
+
def enter(self) -> ta.ContextManager[None]:
|
38
|
+
raise NotImplementedError
|
@@ -0,0 +1,128 @@
|
|
1
|
+
# ruff: noqa: UP007
|
2
|
+
import contextlib
|
3
|
+
import dataclasses as dc
|
4
|
+
import signal
|
5
|
+
import sys
|
6
|
+
import typing as ta
|
7
|
+
|
8
|
+
from .. import lang
|
9
|
+
from .base import Bootstrap
|
10
|
+
from .base import ContextBootstrap
|
11
|
+
|
12
|
+
|
13
|
+
if ta.TYPE_CHECKING:
|
14
|
+
import cProfile # noqa
|
15
|
+
import pstats
|
16
|
+
|
17
|
+
from ..diag import threads as diagt
|
18
|
+
|
19
|
+
else:
|
20
|
+
cProfile = lang.proxy_import('cProfile') # noqa
|
21
|
+
pstats = lang.proxy_import('pstats')
|
22
|
+
|
23
|
+
diagt = lang.proxy_import('..diag.threads', __package__)
|
24
|
+
|
25
|
+
|
26
|
+
##
|
27
|
+
|
28
|
+
|
29
|
+
class ProfilingBootstrap(ContextBootstrap['ProfilingBootstrap.Config']):
|
30
|
+
@dc.dataclass(frozen=True)
|
31
|
+
class Config(Bootstrap.Config):
|
32
|
+
enable: bool = False
|
33
|
+
builtins: bool = True
|
34
|
+
|
35
|
+
outfile: ta.Optional[str] = None
|
36
|
+
|
37
|
+
print: bool = False
|
38
|
+
sort: str = 'cumtime'
|
39
|
+
topn: int = 100
|
40
|
+
|
41
|
+
@contextlib.contextmanager
|
42
|
+
def enter(self) -> ta.Iterator[None]:
|
43
|
+
if not self._config.enable:
|
44
|
+
yield
|
45
|
+
return
|
46
|
+
|
47
|
+
prof = cProfile.Profile()
|
48
|
+
prof.enable()
|
49
|
+
try:
|
50
|
+
yield
|
51
|
+
|
52
|
+
finally:
|
53
|
+
prof.disable()
|
54
|
+
prof.create_stats()
|
55
|
+
|
56
|
+
if self._config.print:
|
57
|
+
pstats.Stats(prof) \
|
58
|
+
.strip_dirs() \
|
59
|
+
.sort_stats(self._config.sort) \
|
60
|
+
.print_stats(self._config.topn)
|
61
|
+
|
62
|
+
if self._config.outfile is not None:
|
63
|
+
prof.dump_stats(self._config.outfile)
|
64
|
+
|
65
|
+
|
66
|
+
##
|
67
|
+
|
68
|
+
|
69
|
+
class ThreadDumpBootstrap(ContextBootstrap['ThreadDumpBootstrap.Config']):
|
70
|
+
@dc.dataclass(frozen=True)
|
71
|
+
class Config(Bootstrap.Config):
|
72
|
+
interval_s: ta.Optional[float] = None
|
73
|
+
|
74
|
+
on_sigquit: bool = False
|
75
|
+
|
76
|
+
@contextlib.contextmanager
|
77
|
+
def enter(self) -> ta.Iterator[None]:
|
78
|
+
if self._config.interval_s:
|
79
|
+
tdt = diagt.create_thread_dump_thread(
|
80
|
+
interval_s=self._config.interval_s,
|
81
|
+
start=True,
|
82
|
+
)
|
83
|
+
else:
|
84
|
+
tdt = None
|
85
|
+
|
86
|
+
if self._config.on_sigquit:
|
87
|
+
dump_threads_str = diagt.dump_threads_str
|
88
|
+
|
89
|
+
def handler(signum, frame):
|
90
|
+
print(dump_threads_str(), file=sys.stderr)
|
91
|
+
|
92
|
+
prev_sq = lang.just(signal.signal(signal.SIGQUIT, handler))
|
93
|
+
else:
|
94
|
+
prev_sq = lang.empty()
|
95
|
+
|
96
|
+
try:
|
97
|
+
yield
|
98
|
+
|
99
|
+
finally:
|
100
|
+
if tdt is not None:
|
101
|
+
tdt.stop_nowait()
|
102
|
+
|
103
|
+
if prev_sq.present:
|
104
|
+
signal.signal(signal.SIGQUIT, prev_sq.must())
|
105
|
+
|
106
|
+
|
107
|
+
##
|
108
|
+
|
109
|
+
|
110
|
+
class TimebombBootstrap(ContextBootstrap['TimebombBootstrap.Config']):
|
111
|
+
@dc.dataclass(frozen=True)
|
112
|
+
class Config(Bootstrap.Config):
|
113
|
+
delay_s: ta.Optional[float] = None
|
114
|
+
|
115
|
+
@contextlib.contextmanager
|
116
|
+
def enter(self) -> ta.Iterator[None]:
|
117
|
+
if not self._config.delay_s:
|
118
|
+
yield
|
119
|
+
return
|
120
|
+
|
121
|
+
tbt = diagt.create_timebomb_thread(
|
122
|
+
self._config.delay_s,
|
123
|
+
start=True,
|
124
|
+
)
|
125
|
+
try:
|
126
|
+
yield
|
127
|
+
finally:
|
128
|
+
tbt.stop_nowait()
|
@@ -0,0 +1,81 @@
|
|
1
|
+
"""
|
2
|
+
TODO:
|
3
|
+
- more logging options
|
4
|
+
- a more powerful interface would be run_fn_with_bootstrap..
|
5
|
+
- ./python -m gprof2dot -f pstats prof.pstats | dot -Tpdf -o prof.pstats.pdf && open prof.pstats.pdf
|
6
|
+
- multiprocess profiling - afterfork, suffix with pid
|
7
|
+
|
8
|
+
TODO diag:
|
9
|
+
- yappi
|
10
|
+
- stackscope
|
11
|
+
- https://github.com/pythonspeed/filprofiler
|
12
|
+
- https://pypi.org/project/guppy3/
|
13
|
+
- https://pypi.org/project/memory-profiler/
|
14
|
+
- https://pypi.org/project/Pympler/
|
15
|
+
|
16
|
+
TODO new items:
|
17
|
+
- pydevd connect-back
|
18
|
+
- debugging / pdb
|
19
|
+
- repl server
|
20
|
+
- packaging fixups
|
21
|
+
- daemonize ( https://github.com/thesharp/daemonize/blob/master/daemonize.py )
|
22
|
+
"""
|
23
|
+
# ruff: noqa: UP006
|
24
|
+
import contextlib
|
25
|
+
import typing as ta
|
26
|
+
|
27
|
+
from .. import lang
|
28
|
+
from . import diag # noqa
|
29
|
+
from . import sys # noqa
|
30
|
+
from .base import Bootstrap
|
31
|
+
from .base import ContextBootstrap
|
32
|
+
from .base import SimpleBootstrap
|
33
|
+
|
34
|
+
|
35
|
+
##
|
36
|
+
|
37
|
+
|
38
|
+
BOOTSTRAP_TYPES_BY_NAME: ta.Mapping[str, ta.Type[Bootstrap]] = { # noqa
|
39
|
+
lang.snake_case(cls.__name__[:-len('Bootstrap')]): cls
|
40
|
+
for cls in lang.deep_subclasses(Bootstrap)
|
41
|
+
if not lang.is_abstract_class(cls)
|
42
|
+
}
|
43
|
+
|
44
|
+
BOOTSTRAP_TYPES_BY_CONFIG_TYPE: ta.Mapping[ta.Type[Bootstrap.Config], ta.Type[Bootstrap]] = {
|
45
|
+
cls.Config: cls
|
46
|
+
for cls in BOOTSTRAP_TYPES_BY_NAME.values()
|
47
|
+
}
|
48
|
+
|
49
|
+
|
50
|
+
##
|
51
|
+
|
52
|
+
|
53
|
+
class BootstrapHarness:
|
54
|
+
def __init__(self, lst: ta.Sequence[Bootstrap]) -> None:
|
55
|
+
super().__init__()
|
56
|
+
self._lst = lst
|
57
|
+
|
58
|
+
@contextlib.contextmanager
|
59
|
+
def __call__(self) -> ta.Iterator[None]:
|
60
|
+
with contextlib.ExitStack() as es:
|
61
|
+
for c in self._lst:
|
62
|
+
if isinstance(c, SimpleBootstrap):
|
63
|
+
c.run()
|
64
|
+
elif isinstance(c, ContextBootstrap):
|
65
|
+
es.enter_context(c.enter())
|
66
|
+
else:
|
67
|
+
raise TypeError(c)
|
68
|
+
|
69
|
+
yield
|
70
|
+
|
71
|
+
|
72
|
+
##
|
73
|
+
|
74
|
+
|
75
|
+
@contextlib.contextmanager
|
76
|
+
def bootstrap(*cfgs: Bootstrap.Config) -> ta.Iterator[None]:
|
77
|
+
with BootstrapHarness([
|
78
|
+
BOOTSTRAP_TYPES_BY_CONFIG_TYPE[type(c)](c)
|
79
|
+
for c in cfgs
|
80
|
+
])():
|
81
|
+
yield
|
@@ -0,0 +1,183 @@
|
|
1
|
+
# ruff: noqa: UP006 UP007
|
2
|
+
import argparse
|
3
|
+
import dataclasses as dc
|
4
|
+
import io
|
5
|
+
import itertools
|
6
|
+
import sys
|
7
|
+
import typing as ta
|
8
|
+
|
9
|
+
from .. import lang
|
10
|
+
from .base import Bootstrap
|
11
|
+
from .harness import BOOTSTRAP_TYPES_BY_NAME
|
12
|
+
from .harness import bootstrap
|
13
|
+
|
14
|
+
|
15
|
+
if ta.TYPE_CHECKING:
|
16
|
+
import runpy
|
17
|
+
|
18
|
+
else:
|
19
|
+
runpy = lang.proxy_import('runpy')
|
20
|
+
|
21
|
+
|
22
|
+
##
|
23
|
+
|
24
|
+
|
25
|
+
class _OrderedArgsAction(argparse.Action):
|
26
|
+
def __call__(self, parser, namespace, values, option_string=None):
|
27
|
+
if 'ordered_args' not in namespace:
|
28
|
+
setattr(namespace, 'ordered_args', [])
|
29
|
+
if self.const is not None:
|
30
|
+
value = self.const
|
31
|
+
else:
|
32
|
+
value = values
|
33
|
+
namespace.ordered_args.append((self.dest, value))
|
34
|
+
|
35
|
+
|
36
|
+
def _or_opt(ty):
|
37
|
+
return (ty, ta.Optional[ty])
|
38
|
+
|
39
|
+
|
40
|
+
def _int_or_str(v):
|
41
|
+
try:
|
42
|
+
return int(v)
|
43
|
+
except ValueError:
|
44
|
+
return v
|
45
|
+
|
46
|
+
|
47
|
+
def _add_arguments(parser: argparse.ArgumentParser) -> None:
|
48
|
+
# ta.Optional[ta.Mapping[str, ta.Tuple[ta.Optional[int], ta.Optional[int]]]]
|
49
|
+
|
50
|
+
for cname, cls in BOOTSTRAP_TYPES_BY_NAME.items():
|
51
|
+
for fld in dc.fields(cls.Config):
|
52
|
+
aname = f'--{cname}:{fld.name}'
|
53
|
+
kw: ta.Dict[str, ta.Any] = {}
|
54
|
+
|
55
|
+
if fld.type in _or_opt(str):
|
56
|
+
pass
|
57
|
+
elif fld.type in _or_opt(bool):
|
58
|
+
kw.update(const=True, nargs=0)
|
59
|
+
elif fld.type in _or_opt(int):
|
60
|
+
kw.update(type=int)
|
61
|
+
elif fld.type in _or_opt(float):
|
62
|
+
kw.update(type=float)
|
63
|
+
elif fld.type in _or_opt(ta.Union[int, str]):
|
64
|
+
kw.update(type=_int_or_str)
|
65
|
+
|
66
|
+
elif fld.type in (
|
67
|
+
*_or_opt(ta.Sequence[str]),
|
68
|
+
*_or_opt(ta.Mapping[str, ta.Optional[str]]),
|
69
|
+
*_or_opt(ta.Mapping[int, ta.Union[int, str, None]]),
|
70
|
+
*_or_opt(ta.Mapping[str, ta.Tuple[ta.Optional[int], ta.Optional[int]]]),
|
71
|
+
):
|
72
|
+
if aname[-1] != 's':
|
73
|
+
raise NameError(aname)
|
74
|
+
aname = aname[:-1]
|
75
|
+
|
76
|
+
else:
|
77
|
+
raise TypeError(fld)
|
78
|
+
|
79
|
+
parser.add_argument(aname, action=_OrderedArgsAction, **kw)
|
80
|
+
|
81
|
+
|
82
|
+
def _process_arguments(args: ta.Any) -> ta.Sequence[Bootstrap.Config]:
|
83
|
+
if not (oa := getattr(args, 'ordered_args', None)):
|
84
|
+
return []
|
85
|
+
|
86
|
+
cfgs: ta.List[Bootstrap.Config] = []
|
87
|
+
|
88
|
+
for cname, cargs in [
|
89
|
+
(n, list(g))
|
90
|
+
for n, g in
|
91
|
+
itertools.groupby(oa, key=lambda s: s[0].partition(':')[0])
|
92
|
+
]:
|
93
|
+
ccls = BOOTSTRAP_TYPES_BY_NAME[cname].Config
|
94
|
+
flds = {f.name: f for f in dc.fields(ccls)}
|
95
|
+
|
96
|
+
kw: ta.Dict[str, ta.Any] = {}
|
97
|
+
for aname, aval in cargs:
|
98
|
+
k = aname.partition(':')[2]
|
99
|
+
|
100
|
+
if k not in flds:
|
101
|
+
k += 's'
|
102
|
+
fld = flds[k]
|
103
|
+
|
104
|
+
if fld.type in _or_opt(ta.Sequence[str]):
|
105
|
+
kw.setdefault(k, []).append(aval)
|
106
|
+
|
107
|
+
elif fld.type in _or_opt(ta.Mapping[str, ta.Optional[str]]):
|
108
|
+
if '=' not in aval:
|
109
|
+
kw.setdefault(k, {})[aval] = None
|
110
|
+
else:
|
111
|
+
ek, _, ev = aval.partition('=')
|
112
|
+
kw.setdefault(k, {})[ek] = ev
|
113
|
+
|
114
|
+
elif fld.type in _or_opt(ta.Mapping[int, ta.Union[int, str, None]]):
|
115
|
+
fk, _, fv = aval.partition('=')
|
116
|
+
if not fv:
|
117
|
+
kw.setdefault(k, {})[int(fk)] = None
|
118
|
+
else:
|
119
|
+
kw.setdefault(k, {})[int(fk)] = _int_or_str(fv)
|
120
|
+
|
121
|
+
elif fld.type in _or_opt(ta.Mapping[str, ta.Tuple[ta.Optional[int], ta.Optional[int]]]):
|
122
|
+
fk, _, fv = aval.partition('=')
|
123
|
+
if ',' in fv:
|
124
|
+
tl, tr = fv.split(',')
|
125
|
+
else:
|
126
|
+
tl, tr = None, None
|
127
|
+
kw.setdefault(k, {})[fk] = (_int_or_str(tl) if tl else None, _int_or_str(tr) if tr else None)
|
128
|
+
|
129
|
+
else:
|
130
|
+
raise TypeError(fld)
|
131
|
+
|
132
|
+
else:
|
133
|
+
kw[k] = aval
|
134
|
+
|
135
|
+
cfg = ccls(**kw)
|
136
|
+
cfgs.append(cfg)
|
137
|
+
|
138
|
+
return cfgs
|
139
|
+
|
140
|
+
|
141
|
+
##
|
142
|
+
|
143
|
+
|
144
|
+
def _main() -> int:
|
145
|
+
parser = argparse.ArgumentParser()
|
146
|
+
|
147
|
+
_add_arguments(parser)
|
148
|
+
|
149
|
+
parser.add_argument('-m', '--module', action='store_true')
|
150
|
+
parser.add_argument('target')
|
151
|
+
parser.add_argument('args', nargs=argparse.REMAINDER)
|
152
|
+
|
153
|
+
args = parser.parse_args()
|
154
|
+
cfgs = _process_arguments(args)
|
155
|
+
|
156
|
+
with bootstrap(*cfgs):
|
157
|
+
tgt = args.target
|
158
|
+
|
159
|
+
if args.module:
|
160
|
+
sys.argv = [tgt, *(args.args or ())]
|
161
|
+
runpy._run_module_as_main(tgt) # type: ignore # noqa
|
162
|
+
|
163
|
+
else:
|
164
|
+
with io.open_code(tgt) as fp:
|
165
|
+
src = fp.read()
|
166
|
+
|
167
|
+
ns = dict(
|
168
|
+
__name__='__main__',
|
169
|
+
__file__=tgt,
|
170
|
+
__builtins__=__builtins__,
|
171
|
+
__spec__=None,
|
172
|
+
)
|
173
|
+
|
174
|
+
import __main__ # noqa
|
175
|
+
__main__.__dict__.clear()
|
176
|
+
__main__.__dict__.update(ns)
|
177
|
+
exec(compile(src, tgt, 'exec'), __main__.__dict__, __main__.__dict__)
|
178
|
+
|
179
|
+
return 0
|
180
|
+
|
181
|
+
|
182
|
+
if __name__ == '__main__':
|
183
|
+
sys.exit(_main())
|