omlish 0.0.0.dev27__tar.gz → 0.0.0.dev28__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.dev27/omlish.egg-info → omlish-0.0.0.dev28}/PKG-INFO +1 -1
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/__about__.py +2 -2
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/dataclasses/impl/api.py +2 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/dataclasses/impl/params.py +2 -1
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/docker.py +2 -2
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lang/descriptors.py +5 -5
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/marshal/__init__.py +5 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/marshal/objects.py +45 -0
- omlish-0.0.0.dev28/omlish/text/asdl.py +528 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28/omlish.egg-info}/PKG-INFO +1 -1
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish.egg-info/SOURCES.txt +1 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/pyproject.toml +1 -1
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/LICENSE +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/MANIFEST.in +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/README.rst +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/.manifests.json +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/argparse.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/asyncs/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/asyncs/anyio.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/asyncs/asyncio.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/asyncs/asyncs.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/asyncs/bridge.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/asyncs/flavors.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/asyncs/trio.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/asyncs/trio_asyncio.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/bootstrap/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/bootstrap/__main__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/bootstrap/base.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/bootstrap/diag.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/bootstrap/harness.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/bootstrap/main.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/bootstrap/marshal.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/bootstrap/sys.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/c3.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/cached.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/check.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/collections/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/collections/_abc.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/collections/_io_abc.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/collections/cache/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/collections/cache/descriptor.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/collections/cache/impl.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/collections/cache/types.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/collections/coerce.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/collections/exceptions.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/collections/frozen.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/collections/identity.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/collections/indexed.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/collections/mappings.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/collections/ordered.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/collections/persistent.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/collections/skiplist.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/collections/sorted.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/collections/treap.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/collections/treapmap.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/collections/unmodifiable.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/collections/utils.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/concurrent/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/concurrent/executors.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/concurrent/futures.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/concurrent/threadlets.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/configs/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/configs/classes.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/configs/flattening.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/configs/strings.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/dataclasses/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/dataclasses/impl/LICENSE +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/dataclasses/impl/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/dataclasses/impl/as_.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/dataclasses/impl/copy.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/dataclasses/impl/descriptors.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/dataclasses/impl/exceptions.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/dataclasses/impl/fields.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/dataclasses/impl/frozen.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/dataclasses/impl/hashing.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/dataclasses/impl/init.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/dataclasses/impl/internals.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/dataclasses/impl/main.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/dataclasses/impl/metaclass.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/dataclasses/impl/metadata.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/dataclasses/impl/order.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/dataclasses/impl/processing.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/dataclasses/impl/reflect.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/dataclasses/impl/replace.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/dataclasses/impl/repr.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/dataclasses/impl/simple.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/dataclasses/impl/slots.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/dataclasses/impl/utils.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/dataclasses/utils.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/datetimes.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/defs.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/diag/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/diag/asts.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/diag/procfs.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/diag/procstats.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/diag/ps.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/diag/pycharm.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/diag/pydevd.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/diag/replserver/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/diag/replserver/__main__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/diag/replserver/console.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/diag/replserver/server.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/diag/threads.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/dispatch/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/dispatch/_dispatch2.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/dispatch/_dispatch3.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/dispatch/dispatch.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/dispatch/functions.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/dispatch/methods.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/dynamic.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/fnpairs.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/formats/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/formats/dotenv.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/formats/json.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/formats/props.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/formats/yaml.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/genmachine.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/graphs/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/graphs/dags.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/graphs/domination.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/graphs/dot/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/graphs/dot/items.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/graphs/dot/make.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/graphs/dot/rendering.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/graphs/dot/utils.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/graphs/trees.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/http/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/http/asgi.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/http/collections.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/http/consts.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/http/cookies.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/http/dates.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/http/encodings.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/http/json.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/http/sessions.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/http/wsgi.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/inject/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/inject/binder.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/inject/bindings.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/inject/eagers.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/inject/elements.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/inject/exceptions.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/inject/impl/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/inject/impl/bindings.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/inject/impl/elements.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/inject/impl/injector.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/inject/impl/inspect.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/inject/impl/multis.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/inject/impl/origins.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/inject/impl/privates.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/inject/impl/providers.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/inject/impl/proxy.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/inject/impl/scopes.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/inject/injector.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/inject/inspect.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/inject/keys.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/inject/listeners.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/inject/managed.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/inject/multis.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/inject/origins.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/inject/overrides.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/inject/privates.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/inject/providers.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/inject/scopes.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/inject/types.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/inject/utils.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/iterators.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lang/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lang/cached.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lang/classes/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lang/classes/abstract.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lang/classes/restrict.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lang/classes/simple.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lang/classes/virtual.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lang/clsdct.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lang/cmp.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lang/contextmanagers.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lang/datetimes.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lang/exceptions.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lang/functions.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lang/imports.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lang/iterables.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lang/maybes.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lang/objects.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lang/resolving.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lang/resources.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lang/strings.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lang/sys.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lang/timeouts.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lang/typing.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/libc.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lifecycles/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lifecycles/abstract.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lifecycles/base.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lifecycles/contextmanagers.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lifecycles/controller.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lifecycles/manager.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lifecycles/states.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lifecycles/transitions.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lite/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lite/cached.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lite/check.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lite/contextmanagers.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lite/json.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lite/logs.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lite/marshal.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lite/reflect.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lite/runtime.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lite/secrets.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lite/strings.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/lite/subprocesses.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/logs/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/logs/_abc.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/logs/configs.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/logs/formatters.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/logs/handlers.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/logs/noisy.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/logs/utils.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/marshal/any.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/marshal/base.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/marshal/base64.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/marshal/dataclasses.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/marshal/datetimes.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/marshal/enums.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/marshal/exceptions.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/marshal/factories.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/marshal/forbidden.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/marshal/global_.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/marshal/helpers.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/marshal/iterables.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/marshal/mappings.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/marshal/maybes.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/marshal/naming.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/marshal/numbers.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/marshal/optionals.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/marshal/polymorphism.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/marshal/primitives.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/marshal/registries.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/marshal/standard.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/marshal/unions.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/marshal/utils.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/marshal/uuids.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/marshal/values.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/matchfns.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/math.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/multiprocessing.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/os.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/reflect/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/reflect/isinstance.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/reflect/ops.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/reflect/subst.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/reflect/types.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/runmodule.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/secrets/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/secrets/crypto.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/secrets/marshal.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/secrets/openssl.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/secrets/passwords.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/secrets/secrets.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/secrets/subprocesses.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/specs/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/specs/jsonschema/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/specs/jsonschema/keywords/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/specs/jsonschema/keywords/base.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/specs/jsonschema/keywords/core.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/specs/jsonschema/keywords/metadata.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/specs/jsonschema/keywords/parse.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/specs/jsonschema/keywords/render.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/specs/jsonschema/keywords/validation.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/specs/jsonschema/schemas/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/specs/jsonschema/schemas/draft202012/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/specs/jsonschema/schemas/draft202012/metaschema.json +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/specs/jsonschema/schemas/draft202012/vocabularies/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/specs/jsonschema/schemas/draft202012/vocabularies/applicator.json +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/specs/jsonschema/schemas/draft202012/vocabularies/content.json +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/specs/jsonschema/schemas/draft202012/vocabularies/core.json +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/specs/jsonschema/schemas/draft202012/vocabularies/format-annotation.json +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/specs/jsonschema/schemas/draft202012/vocabularies/format-assertion.json +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/specs/jsonschema/schemas/draft202012/vocabularies/format.json +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/specs/jsonschema/schemas/draft202012/vocabularies/meta-data.json +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/specs/jsonschema/schemas/draft202012/vocabularies/unevaluated.json +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/specs/jsonschema/schemas/draft202012/vocabularies/validation.json +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/specs/jsonschema/types.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/sql/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/sql/_abc.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/sql/asyncs.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/sql/dbs.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/sql/duckdb.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/sql/exprs.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/sql/qualifiedname.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/sql/secrets.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/sql/sqlean.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/stats.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/sync.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/term.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/testing/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/testing/pytest/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/testing/pytest/helpers.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/testing/pytest/inject/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/testing/pytest/inject/harness.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/testing/pytest/marks.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/testing/pytest/plugins/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/testing/pytest/plugins/_registry.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/testing/pytest/plugins/asyncs.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/testing/pytest/plugins/depskip.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/testing/pytest/plugins/logging.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/testing/pytest/plugins/managermarks.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/testing/pytest/plugins/pydevd.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/testing/pytest/plugins/repeat.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/testing/pytest/plugins/skips.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/testing/pytest/plugins/spacing.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/testing/pytest/plugins/switches.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/testing/pytest/plugins/utils.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/testing/testing.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/text/__init__.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/text/delimit.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/text/glyphsplit.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/text/indent.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish/text/parts.py +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish.egg-info/dependency_links.txt +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish.egg-info/requires.txt +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/omlish.egg-info/top_level.txt +0 -0
- {omlish-0.0.0.dev27 → omlish-0.0.0.dev28}/setup.cfg +0 -0
@@ -36,6 +36,7 @@ def field( # noqa
|
|
36
36
|
check_type: bool | None = None,
|
37
37
|
override: bool = False,
|
38
38
|
repr_fn: ta.Callable[[ta.Any], str | None] | None = None,
|
39
|
+
frozen: bool | None = None,
|
39
40
|
): # -> dc.Field
|
40
41
|
if default is not MISSING and default_factory is not MISSING:
|
41
42
|
raise ValueError('cannot specify both default and default_factory')
|
@@ -47,6 +48,7 @@ def field( # noqa
|
|
47
48
|
check_type=check_type,
|
48
49
|
override=override,
|
49
50
|
repr_fn=repr_fn,
|
51
|
+
frozen=frozen,
|
50
52
|
)
|
51
53
|
|
52
54
|
md: ta.Mapping = {FieldExtras: fx}
|
@@ -42,12 +42,13 @@ from .metadata import METADATA_ATTR
|
|
42
42
|
|
43
43
|
@dc.dataclass(frozen=True, kw_only=True)
|
44
44
|
class FieldExtras(lang.Final):
|
45
|
-
derive: ta.Callable[..., ta.Any] | None = None
|
45
|
+
derive: ta.Callable[..., ta.Any] | None = None # TODO
|
46
46
|
coerce: bool | ta.Callable[[ta.Any], ta.Any] | None = None
|
47
47
|
validate: ta.Callable[[ta.Any], bool] | None = None
|
48
48
|
check_type: bool | None = None
|
49
49
|
override: bool = False
|
50
50
|
repr_fn: ta.Callable[[ta.Any], str | None] | None = None
|
51
|
+
frozen: bool | None = None # TODO
|
51
52
|
|
52
53
|
|
53
54
|
DEFAULT_FIELD_EXTRAS = FieldExtras()
|
@@ -170,9 +170,9 @@ _LIKELY_IN_DOCKER_PATTERN = re.compile(r'^overlay / .*/docker/')
|
|
170
170
|
|
171
171
|
|
172
172
|
def is_likely_in_docker() -> bool:
|
173
|
-
if sys
|
173
|
+
if getattr(sys, 'platform') != 'linux':
|
174
174
|
return False
|
175
|
-
with open('/proc/mounts') as f:
|
175
|
+
with open('/proc/mounts') as f:
|
176
176
|
ls = f.readlines()
|
177
177
|
return any(_LIKELY_IN_DOCKER_PATTERN.match(l) for l in ls)
|
178
178
|
|
@@ -57,11 +57,6 @@ def unwrap_method_descriptors(fn: ta.Callable) -> ta.Callable:
|
|
57
57
|
##
|
58
58
|
|
59
59
|
|
60
|
-
def unwrap_func(fn: ta.Callable) -> ta.Callable:
|
61
|
-
fn, _ = unwrap_func_with_partials(fn)
|
62
|
-
return fn
|
63
|
-
|
64
|
-
|
65
60
|
def unwrap_func_with_partials(fn: ta.Callable) -> tuple[ta.Callable, list[functools.partial]]:
|
66
61
|
ps = []
|
67
62
|
while True:
|
@@ -88,6 +83,11 @@ def unwrap_func_with_partials(fn: ta.Callable) -> tuple[ta.Callable, list[functo
|
|
88
83
|
return fn, ps
|
89
84
|
|
90
85
|
|
86
|
+
def unwrap_func(fn: ta.Callable) -> ta.Callable:
|
87
|
+
uw, _ = unwrap_func_with_partials(fn)
|
88
|
+
return uw
|
89
|
+
|
90
|
+
|
91
91
|
##
|
92
92
|
|
93
93
|
|
@@ -55,8 +55,13 @@ from .helpers import ( # noqa
|
|
55
55
|
)
|
56
56
|
|
57
57
|
from .objects import ( # noqa
|
58
|
+
FieldInfo,
|
58
59
|
FieldMetadata,
|
60
|
+
ObjectMarshaler,
|
59
61
|
ObjectMetadata,
|
62
|
+
ObjectUnmarshaler,
|
63
|
+
SimpleObjectMarshalerFactory,
|
64
|
+
SimpleObjectUnmarshalerFactory,
|
60
65
|
)
|
61
66
|
|
62
67
|
from .polymorphism import ( # noqa
|
@@ -9,6 +9,7 @@ import typing as ta
|
|
9
9
|
|
10
10
|
from .. import check
|
11
11
|
from .. import dataclasses as dc
|
12
|
+
from .. import reflect as rfl
|
12
13
|
from .base import MarshalContext
|
13
14
|
from .base import Marshaler
|
14
15
|
from .base import MarshalerFactory
|
@@ -87,6 +88,27 @@ class ObjectMarshaler(Marshaler):
|
|
87
88
|
return ret
|
88
89
|
|
89
90
|
|
91
|
+
@dc.dataclass(frozen=True)
|
92
|
+
class SimpleObjectMarshalerFactory(MarshalerFactory):
|
93
|
+
dct: ta.Mapping[type, ta.Sequence[FieldInfo]]
|
94
|
+
unknown_field: str | None = None
|
95
|
+
|
96
|
+
def guard(self, ctx: MarshalContext, rty: rfl.Type) -> bool:
|
97
|
+
return isinstance(rty, type) and rty in self.dct
|
98
|
+
|
99
|
+
def fn(self, ctx: MarshalContext, rty: rfl.Type) -> Marshaler:
|
100
|
+
ty = check.isinstance(rty, type)
|
101
|
+
flds = self.dct[ty]
|
102
|
+
fields = [
|
103
|
+
(fi, ctx.make(fi.type))
|
104
|
+
for fi in flds
|
105
|
+
]
|
106
|
+
return ObjectMarshaler(
|
107
|
+
fields,
|
108
|
+
unknown_field=self.unknown_field,
|
109
|
+
)
|
110
|
+
|
111
|
+
|
90
112
|
##
|
91
113
|
|
92
114
|
|
@@ -123,3 +145,26 @@ class ObjectUnmarshaler(Unmarshaler):
|
|
123
145
|
kw[fi.name] = u.unmarshal(ctx, mv)
|
124
146
|
|
125
147
|
return self.cls(**kw)
|
148
|
+
|
149
|
+
|
150
|
+
@dc.dataclass(frozen=True)
|
151
|
+
class SimpleObjectUnmarshalerFactory(UnmarshalerFactory):
|
152
|
+
dct: ta.Mapping[type, ta.Sequence[FieldInfo]]
|
153
|
+
unknown_field: str | None = None
|
154
|
+
|
155
|
+
def guard(self, ctx: UnmarshalContext, rty: rfl.Type) -> bool:
|
156
|
+
return isinstance(rty, type) and rty in self.dct
|
157
|
+
|
158
|
+
def fn(self, ctx: UnmarshalContext, rty: rfl.Type) -> Unmarshaler:
|
159
|
+
ty = check.isinstance(rty, type)
|
160
|
+
flds = self.dct[ty]
|
161
|
+
fields_by_unmarshal_name = {
|
162
|
+
n: (fi, ctx.make(fi.type))
|
163
|
+
for fi in flds
|
164
|
+
for n in fi.unmarshal_names
|
165
|
+
}
|
166
|
+
return ObjectUnmarshaler(
|
167
|
+
ty,
|
168
|
+
fields_by_unmarshal_name,
|
169
|
+
unknown_field=self.unknown_field,
|
170
|
+
)
|
@@ -0,0 +1,528 @@
|
|
1
|
+
"""
|
2
|
+
https://github.com/python/cpython/blob/21d2a9ab2f4dcbf1be462d3b7f7a231a46bc1cb7/Parser/asdl.py
|
3
|
+
|
4
|
+
-------------------------------------------------------------------------------
|
5
|
+
|
6
|
+
Parser for ASDL [1] definition files. Reads in an ASDL description and parses it into an AST that describes it.
|
7
|
+
|
8
|
+
The EBNF we're parsing here: Figure 1 of the paper [1]. Extended to support modules and attributes after a product.
|
9
|
+
Words starting with Capital letters are terminals. Literal tokens are in "double quotes". Others are non-terminals. Id
|
10
|
+
is either TokenId or ConstructorId.
|
11
|
+
|
12
|
+
module ::= "module" Id "{" [definitions] "}"
|
13
|
+
definitions ::= { TypeId "=" type }
|
14
|
+
type ::= product | sum
|
15
|
+
product ::= fields ["attributes" fields]
|
16
|
+
fields ::= "(" { field, "," } field ")"
|
17
|
+
field ::= TypeId ["?" | "*"] [Id]
|
18
|
+
sum ::= constructor { "|" constructor } ["attributes" fields]
|
19
|
+
constructor ::= ConstructorId [fields]
|
20
|
+
|
21
|
+
[1] "The Zephyr Abstract Syntax Description Language" by Wang, et. al. See http://asdl.sourceforge.net/
|
22
|
+
"""
|
23
|
+
# PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
|
24
|
+
# --------------------------------------------
|
25
|
+
#
|
26
|
+
# 1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and the Individual or Organization
|
27
|
+
# ("Licensee") accessing and otherwise using this software ("Python") in source or binary form and its associated
|
28
|
+
# documentation.
|
29
|
+
#
|
30
|
+
# 2. Subject to the terms and conditions of this License Agreement, PSF hereby grants Licensee a nonexclusive,
|
31
|
+
# royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative
|
32
|
+
# works, distribute, and otherwise use Python alone or in any derivative version, provided, however, that PSF's License
|
33
|
+
# Agreement and PSF's notice of copyright, i.e., "Copyright (c) 2001-2024 Python Software Foundation; All Rights
|
34
|
+
# Reserved" are retained in Python alone or in any derivative version prepared by Licensee.
|
35
|
+
#
|
36
|
+
# 3. In the event Licensee prepares a derivative work that is based on or incorporates Python or any part thereof, and
|
37
|
+
# wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in
|
38
|
+
# any such work a brief summary of the changes made to Python.
|
39
|
+
#
|
40
|
+
# 4. PSF is making Python available to Licensee on an "AS IS" basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES,
|
41
|
+
# EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY
|
42
|
+
# OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT INFRINGE ANY THIRD PARTY
|
43
|
+
# RIGHTS.
|
44
|
+
#
|
45
|
+
# 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL
|
46
|
+
# DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, OR ANY DERIVATIVE THEREOF, EVEN IF
|
47
|
+
# ADVISED OF THE POSSIBILITY THEREOF.
|
48
|
+
#
|
49
|
+
# 6. This License Agreement will automatically terminate upon a material breach of its terms and conditions.
|
50
|
+
#
|
51
|
+
# 7. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint
|
52
|
+
# venture between PSF and Licensee. This License Agreement does not grant permission to use PSF trademarks or trade
|
53
|
+
# name in a trademark sense to endorse or promote products or services of Licensee, or any third party.
|
54
|
+
#
|
55
|
+
# 8. By copying, installing or otherwise using Python, Licensee agrees to be bound by the terms and conditions of this
|
56
|
+
# License Agreement.
|
57
|
+
# ruff: noqa: N802
|
58
|
+
import abc
|
59
|
+
import dataclasses as dc
|
60
|
+
import enum
|
61
|
+
import re
|
62
|
+
import typing as ta
|
63
|
+
|
64
|
+
from .. import cached
|
65
|
+
from .. import check
|
66
|
+
|
67
|
+
|
68
|
+
##
|
69
|
+
|
70
|
+
|
71
|
+
# The following classes define nodes into which the Asdl description is parsed. Note: this is a "meta-AST". Asdl files
|
72
|
+
# (such as Python.asdl) describe the AST structure used by a programming language. But Asdl files themselves need to be
|
73
|
+
# parsed. This module parses Asdl files and uses a simple AST to represent them. See the EBNF at the top of the file to
|
74
|
+
# understand the logical connection between the various node types.
|
75
|
+
|
76
|
+
class Ast(abc.ABC):
|
77
|
+
@abc.abstractmethod
|
78
|
+
def __repr__(self) -> str:
|
79
|
+
raise NotImplementedError
|
80
|
+
|
81
|
+
|
82
|
+
@dc.dataclass(frozen=True)
|
83
|
+
class Field(Ast):
|
84
|
+
type: str
|
85
|
+
name: str | None = None
|
86
|
+
seq: bool = False
|
87
|
+
opt: bool = False
|
88
|
+
|
89
|
+
def __str__(self) -> str:
|
90
|
+
if self.seq:
|
91
|
+
extra = '*'
|
92
|
+
elif self.opt:
|
93
|
+
extra = '?'
|
94
|
+
else:
|
95
|
+
extra = ''
|
96
|
+
|
97
|
+
return f'{self.type}{extra} {self.name}'
|
98
|
+
|
99
|
+
def __repr__(self) -> str:
|
100
|
+
if self.seq:
|
101
|
+
extra = ', seq=True'
|
102
|
+
elif self.opt:
|
103
|
+
extra = ', opt=True'
|
104
|
+
else:
|
105
|
+
extra = ''
|
106
|
+
if self.name is None:
|
107
|
+
return f'Field({self.type}{extra})'
|
108
|
+
else:
|
109
|
+
return f'Field({self.type}, {self.name}{extra})'
|
110
|
+
|
111
|
+
|
112
|
+
@dc.dataclass(frozen=True)
|
113
|
+
class Constructor(Ast):
|
114
|
+
name: str
|
115
|
+
fields: ta.Sequence[Field] | None = None
|
116
|
+
|
117
|
+
def __repr__(self) -> str:
|
118
|
+
return f'Constructor({self.name}, {self.fields})'
|
119
|
+
|
120
|
+
|
121
|
+
@dc.dataclass(frozen=True)
|
122
|
+
class Sum(Ast):
|
123
|
+
types: ta.Sequence[Constructor]
|
124
|
+
attributes: ta.Sequence[Field] | None = None
|
125
|
+
|
126
|
+
def __repr__(self) -> str:
|
127
|
+
if self.attributes:
|
128
|
+
return f'Sum({self.types}, {self.attributes})'
|
129
|
+
else:
|
130
|
+
return f'Sum({self.types})'
|
131
|
+
|
132
|
+
|
133
|
+
@dc.dataclass(frozen=True)
|
134
|
+
class Product(Ast):
|
135
|
+
fields: ta.Sequence[Field]
|
136
|
+
attributes: ta.Sequence[Field] | None = None
|
137
|
+
|
138
|
+
def __repr__(self) -> str:
|
139
|
+
if self.attributes:
|
140
|
+
return f'Product({self.fields}, {self.attributes})'
|
141
|
+
else:
|
142
|
+
return f'Product({self.fields})'
|
143
|
+
|
144
|
+
|
145
|
+
@dc.dataclass(frozen=True)
|
146
|
+
class Type(Ast):
|
147
|
+
name: str
|
148
|
+
value: Sum | Product
|
149
|
+
|
150
|
+
def __repr__(self) -> str:
|
151
|
+
return f'Type({self.name}, {self.value})'
|
152
|
+
|
153
|
+
|
154
|
+
@dc.dataclass(frozen=True)
|
155
|
+
class Module(Ast):
|
156
|
+
name: str
|
157
|
+
dfns: ta.Sequence[Type]
|
158
|
+
|
159
|
+
@cached.property
|
160
|
+
def types(self) -> ta.Mapping[str, Sum | Product]:
|
161
|
+
return {ty.name: ty.value for ty in self.dfns}
|
162
|
+
|
163
|
+
def __repr__(self) -> str:
|
164
|
+
return f'Module({self.name}, {self.dfns})'
|
165
|
+
|
166
|
+
|
167
|
+
##
|
168
|
+
|
169
|
+
|
170
|
+
# A generic visitor for the meta-Ast that describes Asdl. This can be used by emitters. Note that this visitor does not
|
171
|
+
# provide a generic visit method, so a subclass needs to define visit methods from visitModule to as deep as the
|
172
|
+
# interesting node.
|
173
|
+
# We also define a Check visitor that makes sure the parsed Asdl is well-formed.
|
174
|
+
|
175
|
+
class VisitorBase:
|
176
|
+
"""Generic tree visitor for Asts."""
|
177
|
+
|
178
|
+
def __init__(self) -> None:
|
179
|
+
super().__init__()
|
180
|
+
self.cache: dict[type, ta.Any] = {}
|
181
|
+
|
182
|
+
def visit(self, obj, *args):
|
183
|
+
klass = obj.__class__
|
184
|
+
meth = self.cache.get(klass)
|
185
|
+
if meth is None:
|
186
|
+
methname = 'visit' + klass.__name__
|
187
|
+
meth = getattr(self, methname, None)
|
188
|
+
self.cache[klass] = meth
|
189
|
+
if meth:
|
190
|
+
try:
|
191
|
+
meth(obj, *args)
|
192
|
+
except Exception as e:
|
193
|
+
raise Exception(f'Error visiting {obj!r}') from e
|
194
|
+
|
195
|
+
|
196
|
+
##
|
197
|
+
|
198
|
+
|
199
|
+
BUILTIN_TYPES: ta.AbstractSet[str] = {
|
200
|
+
'identifier',
|
201
|
+
'string',
|
202
|
+
'int',
|
203
|
+
'constant',
|
204
|
+
}
|
205
|
+
|
206
|
+
|
207
|
+
##
|
208
|
+
|
209
|
+
|
210
|
+
# Types for describing tokens in an Asdl specification.
|
211
|
+
class TokenKind(enum.IntEnum):
|
212
|
+
"""TokenKind is provides a scope for enumerated token kinds."""
|
213
|
+
|
214
|
+
CONSTRUCTOR_ID = enum.auto()
|
215
|
+
TYPE_ID = enum.auto()
|
216
|
+
EQUALS = enum.auto()
|
217
|
+
COMMA = enum.auto()
|
218
|
+
QUESTION = enum.auto()
|
219
|
+
PIPE = enum.auto()
|
220
|
+
AstERISK = enum.auto()
|
221
|
+
L_PAREN = enum.auto()
|
222
|
+
R_PAREN = enum.auto()
|
223
|
+
L_BRACE = enum.auto()
|
224
|
+
R_BRACE = enum.auto()
|
225
|
+
|
226
|
+
|
227
|
+
OPERATOR_TABLE: ta.Mapping[str, TokenKind] = {
|
228
|
+
'=': TokenKind.EQUALS,
|
229
|
+
',': TokenKind.COMMA,
|
230
|
+
'?': TokenKind.QUESTION,
|
231
|
+
'|': TokenKind.PIPE,
|
232
|
+
'(': TokenKind.L_PAREN,
|
233
|
+
')': TokenKind.R_PAREN,
|
234
|
+
'*': TokenKind.AstERISK,
|
235
|
+
'{': TokenKind.L_BRACE,
|
236
|
+
'}': TokenKind.R_BRACE,
|
237
|
+
}
|
238
|
+
|
239
|
+
|
240
|
+
@dc.dataclass(frozen=True)
|
241
|
+
class Token:
|
242
|
+
kind: TokenKind
|
243
|
+
value: str
|
244
|
+
lineno: int
|
245
|
+
|
246
|
+
|
247
|
+
class AsdlSyntaxError(Exception):
|
248
|
+
def __init__(self, msg: str, lineno: int | None = None) -> None:
|
249
|
+
super().__init__()
|
250
|
+
self.msg = msg
|
251
|
+
self.lineno = lineno or '<unknown>'
|
252
|
+
|
253
|
+
def __str__(self) -> str:
|
254
|
+
return f'Syntax error on line {self.lineno}: {self.msg}'
|
255
|
+
|
256
|
+
|
257
|
+
def tokenize_asdl(buf: str) -> ta.Iterator[Token]:
|
258
|
+
"""Tokenize the given buffer. Yield Token objects."""
|
259
|
+
|
260
|
+
for lineno, line in enumerate(buf.splitlines(), 1):
|
261
|
+
for m in re.finditer(r'\s*(\w+|--.*|.)', line.strip()):
|
262
|
+
c = m.group(1)
|
263
|
+
if c[0].isalpha():
|
264
|
+
# Some kind of identifier
|
265
|
+
if c[0].isupper():
|
266
|
+
yield Token(TokenKind.CONSTRUCTOR_ID, c, lineno)
|
267
|
+
else:
|
268
|
+
yield Token(TokenKind.TYPE_ID, c, lineno)
|
269
|
+
elif c[:2] == '--':
|
270
|
+
# Comment
|
271
|
+
break
|
272
|
+
else:
|
273
|
+
# Operators
|
274
|
+
try:
|
275
|
+
op_kind = OPERATOR_TABLE[c]
|
276
|
+
except KeyError:
|
277
|
+
raise AsdlSyntaxError(f'Invalid operator {c}', lineno) # noqa
|
278
|
+
yield Token(op_kind, c, lineno)
|
279
|
+
|
280
|
+
|
281
|
+
##
|
282
|
+
|
283
|
+
|
284
|
+
class AsdlParser:
|
285
|
+
"""
|
286
|
+
Parser for Asdl files.
|
287
|
+
|
288
|
+
Create, then call the parse method on a buffer containing Asdl. This is a simple recursive descent parser that uses
|
289
|
+
tokenize_asdl for the lexing.
|
290
|
+
"""
|
291
|
+
|
292
|
+
def __init__(self) -> None:
|
293
|
+
super().__init__()
|
294
|
+
self._tokenizer: ta.Iterator[Token] | None = None
|
295
|
+
self.cur_token: Token | None = None
|
296
|
+
|
297
|
+
def cur(self) -> Token:
|
298
|
+
return check.not_none(self.cur_token)
|
299
|
+
|
300
|
+
def parse(self, buf: str) -> Module:
|
301
|
+
"""Parse the Asdl in the buffer and return an Ast with a Module root."""
|
302
|
+
|
303
|
+
self._tokenizer = tokenize_asdl(buf)
|
304
|
+
self._advance()
|
305
|
+
return self._parse_module()
|
306
|
+
|
307
|
+
def _parse_module(self) -> Module:
|
308
|
+
if self._at_keyword('module'):
|
309
|
+
self._advance()
|
310
|
+
else:
|
311
|
+
raise AsdlSyntaxError(f'Expected "module" (found {self.cur().value})', self.cur().lineno) # noqa
|
312
|
+
name = self._match(self._id_kinds)
|
313
|
+
self._match(TokenKind.L_BRACE)
|
314
|
+
defs = self._parse_definitions()
|
315
|
+
self._match(TokenKind.R_BRACE)
|
316
|
+
return Module(name, defs)
|
317
|
+
|
318
|
+
def _parse_definitions(self) -> ta.Sequence[Type]:
|
319
|
+
defs = []
|
320
|
+
while self.cur().kind == TokenKind.TYPE_ID:
|
321
|
+
typename = check.non_empty_str(self._advance())
|
322
|
+
self._match(TokenKind.EQUALS)
|
323
|
+
ty = self._parse_type()
|
324
|
+
defs.append(Type(typename, ty))
|
325
|
+
return defs
|
326
|
+
|
327
|
+
def _parse_type(self) -> Sum | Product:
|
328
|
+
if self.cur().kind == TokenKind.L_PAREN:
|
329
|
+
# If we see a (, it's a product
|
330
|
+
return self._parse_product()
|
331
|
+
else:
|
332
|
+
# Otherwise it's a sum. Look for ConstructorId
|
333
|
+
sumlist = [Constructor(self._match(TokenKind.CONSTRUCTOR_ID), self._parse_optional_fields())]
|
334
|
+
while self.cur().kind == TokenKind.PIPE:
|
335
|
+
# More constructors
|
336
|
+
self._advance()
|
337
|
+
sumlist.append(Constructor(
|
338
|
+
self._match(TokenKind.CONSTRUCTOR_ID),
|
339
|
+
self._parse_optional_fields()),
|
340
|
+
)
|
341
|
+
return Sum(sumlist, self._parse_optional_attributes())
|
342
|
+
|
343
|
+
def _parse_product(self) -> Product:
|
344
|
+
return Product(self._parse_fields(), self._parse_optional_attributes())
|
345
|
+
|
346
|
+
def _parse_fields(self) -> ta.Sequence[Field]:
|
347
|
+
fields = []
|
348
|
+
self._match(TokenKind.L_PAREN)
|
349
|
+
while self.cur().kind == TokenKind.TYPE_ID:
|
350
|
+
typename = check.non_empty_str(self._advance())
|
351
|
+
is_seq, is_opt = self._parse_optional_field_quantifier()
|
352
|
+
id = self._advance() if self.cur().kind in self._id_kinds else None # noqa
|
353
|
+
fields.append(Field(typename, id, seq=is_seq, opt=is_opt))
|
354
|
+
if self.cur().kind == TokenKind.R_PAREN:
|
355
|
+
break
|
356
|
+
elif self.cur().kind == TokenKind.COMMA:
|
357
|
+
self._advance()
|
358
|
+
self._match(TokenKind.R_PAREN)
|
359
|
+
return fields
|
360
|
+
|
361
|
+
def _parse_optional_fields(self) -> ta.Sequence[Field] | None:
|
362
|
+
if self.cur().kind == TokenKind.L_PAREN:
|
363
|
+
return self._parse_fields()
|
364
|
+
else:
|
365
|
+
return None
|
366
|
+
|
367
|
+
def _parse_optional_attributes(self) -> ta.Sequence[Field] | None:
|
368
|
+
if self._at_keyword('attributes'):
|
369
|
+
self._advance()
|
370
|
+
return self._parse_fields()
|
371
|
+
else:
|
372
|
+
return None
|
373
|
+
|
374
|
+
def _parse_optional_field_quantifier(self) -> tuple[bool, bool]: # (seq, opt)
|
375
|
+
is_seq, is_opt = False, False
|
376
|
+
if self.cur().kind == TokenKind.AstERISK:
|
377
|
+
is_seq = True
|
378
|
+
self._advance()
|
379
|
+
elif self.cur().kind == TokenKind.QUESTION:
|
380
|
+
is_opt = True
|
381
|
+
self._advance()
|
382
|
+
return is_seq, is_opt
|
383
|
+
|
384
|
+
def _advance(self) -> str | None:
|
385
|
+
"""Return the value of the current token and read the next one into self.cur_token."""
|
386
|
+
|
387
|
+
cur_val = None if self.cur_token is None else self.cur_token.value
|
388
|
+
try:
|
389
|
+
self.cur_token = next(check.not_none(self._tokenizer))
|
390
|
+
except StopIteration:
|
391
|
+
self.cur_token = None
|
392
|
+
return cur_val
|
393
|
+
|
394
|
+
_id_kinds = (TokenKind.CONSTRUCTOR_ID, TokenKind.TYPE_ID)
|
395
|
+
|
396
|
+
def _match(self, kind: TokenKind | tuple[TokenKind, ...]) -> str:
|
397
|
+
"""The 'match' primitive of RD parsers.
|
398
|
+
|
399
|
+
* Verifies that the current token is of the given kind (kind can be a tuple, in which the kind must match one of
|
400
|
+
its members).
|
401
|
+
* Returns the value of the current token
|
402
|
+
* Reads in the next token
|
403
|
+
"""
|
404
|
+
|
405
|
+
if isinstance(kind, tuple) and self.cur().kind in kind or self.cur().kind == kind:
|
406
|
+
value = self.cur().value
|
407
|
+
self._advance()
|
408
|
+
return value
|
409
|
+
else:
|
410
|
+
raise AsdlSyntaxError(
|
411
|
+
f'Unmatched {kind} (found {self.cur().kind})',
|
412
|
+
self.cur().lineno,
|
413
|
+
)
|
414
|
+
|
415
|
+
def _at_keyword(self, keyword: str) -> bool:
|
416
|
+
return self.cur().kind == TokenKind.TYPE_ID and self.cur().value == keyword
|
417
|
+
|
418
|
+
|
419
|
+
##
|
420
|
+
|
421
|
+
|
422
|
+
FlatFieldArity: ta.TypeAlias = ta.Literal[1, '?', '*']
|
423
|
+
|
424
|
+
|
425
|
+
@dc.dataclass(frozen=True)
|
426
|
+
class FlatField:
|
427
|
+
name: str
|
428
|
+
type: str
|
429
|
+
n: FlatFieldArity = 1
|
430
|
+
|
431
|
+
|
432
|
+
@dc.dataclass(frozen=True)
|
433
|
+
class FlatNode(abc.ABC):
|
434
|
+
name: str
|
435
|
+
fields: ta.Sequence[FlatField] = dc.field(default=(), kw_only=True)
|
436
|
+
attributes: ta.Sequence[FlatField] = dc.field(default=(), kw_only=True)
|
437
|
+
|
438
|
+
|
439
|
+
@dc.dataclass(frozen=True)
|
440
|
+
class FlatSum(FlatNode):
|
441
|
+
constructors: ta.Sequence[str] = dc.field(default=(), kw_only=True)
|
442
|
+
|
443
|
+
|
444
|
+
@dc.dataclass(frozen=True)
|
445
|
+
class FlatProduct(FlatNode):
|
446
|
+
pass
|
447
|
+
|
448
|
+
|
449
|
+
@dc.dataclass(frozen=True)
|
450
|
+
class FlatConstructor(FlatNode):
|
451
|
+
sum: str = dc.field(kw_only=True)
|
452
|
+
|
453
|
+
|
454
|
+
def flatten(mod: Module) -> ta.Mapping[str, FlatNode]:
|
455
|
+
lst: list[FlatNode] = []
|
456
|
+
|
457
|
+
def mk_field(af: Field) -> FlatField:
|
458
|
+
return FlatField(
|
459
|
+
check.non_empty_str(af.name),
|
460
|
+
af.type,
|
461
|
+
n='*' if af.seq else '?' if af.opt else 1,
|
462
|
+
)
|
463
|
+
|
464
|
+
def mk_fields(afs: ta.Iterable[Field] | None) -> ta.Sequence[FlatField]:
|
465
|
+
return list(map(mk_field, afs or []))
|
466
|
+
|
467
|
+
for ty in mod.dfns:
|
468
|
+
v = ty.value
|
469
|
+
|
470
|
+
if isinstance(v, Sum):
|
471
|
+
lst.append(FlatSum(
|
472
|
+
ty.name,
|
473
|
+
attributes=mk_fields(v.attributes),
|
474
|
+
constructors=[c.name for c in v.types],
|
475
|
+
))
|
476
|
+
|
477
|
+
for c in v.types:
|
478
|
+
lst.append(FlatConstructor(
|
479
|
+
c.name,
|
480
|
+
fields=mk_fields(c.fields),
|
481
|
+
attributes=mk_fields(v.attributes),
|
482
|
+
sum=ty.name,
|
483
|
+
))
|
484
|
+
|
485
|
+
elif isinstance(v, Product):
|
486
|
+
lst.append(FlatProduct(
|
487
|
+
ty.name,
|
488
|
+
fields=mk_fields(v.fields),
|
489
|
+
attributes=mk_fields(v.attributes),
|
490
|
+
))
|
491
|
+
|
492
|
+
else:
|
493
|
+
raise TypeError(v)
|
494
|
+
|
495
|
+
#
|
496
|
+
|
497
|
+
dct: dict[str, FlatNode] = {}
|
498
|
+
|
499
|
+
for n in lst:
|
500
|
+
if n.name in dct:
|
501
|
+
raise KeyError(n.name)
|
502
|
+
dct[n.name] = n
|
503
|
+
|
504
|
+
return dct
|
505
|
+
|
506
|
+
|
507
|
+
#
|
508
|
+
|
509
|
+
|
510
|
+
def build_fields_info(
|
511
|
+
nodes: ta.Mapping[str, FlatNode],
|
512
|
+
*,
|
513
|
+
exclude_builtins: bool = False,
|
514
|
+
) -> ta.Mapping[str, ta.Mapping[str, tuple[str, FlatFieldArity]]]:
|
515
|
+
dct: dict[str, dict[str, tuple[str, FlatFieldArity]]] = {}
|
516
|
+
for n in nodes.values():
|
517
|
+
cur = {}
|
518
|
+
f: FlatField
|
519
|
+
for f in [*n.fields, *n.attributes]:
|
520
|
+
if f.type in BUILTIN_TYPES:
|
521
|
+
if exclude_builtins:
|
522
|
+
continue
|
523
|
+
elif f.type not in nodes:
|
524
|
+
raise KeyError(f.type)
|
525
|
+
cur[f.name] = (f.type, f.n)
|
526
|
+
if cur:
|
527
|
+
dct[n.name] = cur
|
528
|
+
return dct
|