omdev 0.0.0.dev241__tar.gz → 0.0.0.dev243__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.
- {omdev-0.0.0.dev241/omdev.egg-info → omdev-0.0.0.dev243}/PKG-INFO +2 -2
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ci/ci.py +28 -3
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ci/cli.py +4 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ci/docker/cacheserved/cache.py +9 -11
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ci/docker/cmds.py +18 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/oci/tars.py +2 -10
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/scripts/ci.py +257 -72
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tools/json/parsing.py +2 -6
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243/omdev.egg-info}/PKG-INFO +2 -2
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev.egg-info/requires.txt +1 -1
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/pyproject.toml +2 -2
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/LICENSE +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/MANIFEST.in +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/README.rst +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/.manifests.json +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/__about__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/amalg/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/amalg/__main__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/amalg/gen.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/amalg/imports.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/amalg/main.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/amalg/manifests.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/amalg/resources.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/amalg/srcfiles.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/amalg/strip.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/amalg/types.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/amalg/typing.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/antlr/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/antlr/consts.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/antlr/gen.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/bracepy.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cache/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cache/compute/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cache/compute/cache.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cache/compute/contexts.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cache/compute/currents.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cache/compute/fns.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cache/compute/resolvers.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cache/compute/storage.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cache/compute/types.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cache/data/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cache/data/actions.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cache/data/cache.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cache/data/consts.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cache/data/defaults.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cache/data/manifests.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cache/data/specs.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cc/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cc/__main__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cc/cdeps.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cc/cdeps.toml +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cc/cli.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cexts/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cexts/_boilerplate.cc +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cexts/_distutils/LICENSE +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cexts/_distutils/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cexts/_distutils/build_ext.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cexts/_distutils/compilers/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cexts/_distutils/compilers/ccompiler.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cexts/_distutils/compilers/options.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cexts/_distutils/compilers/unixccompiler.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cexts/_distutils/dir_util.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cexts/_distutils/errors.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cexts/_distutils/extension.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cexts/_distutils/file_util.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cexts/_distutils/modified.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cexts/_distutils/spawn.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cexts/_distutils/sysconfig.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cexts/_distutils/util.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cexts/_distutils/version.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cexts/build.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cexts/cmake.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cexts/importhook.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cexts/magic.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cexts/scan.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ci/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ci/__main__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ci/cache.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ci/compose.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ci/consts.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ci/docker/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ci/docker/buildcaching.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ci/docker/cache.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ci/docker/cacheserved/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ci/docker/cacheserved/manifests.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ci/docker/dataserver.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ci/docker/imagepulling.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ci/docker/inject.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ci/docker/packing.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ci/docker/repositories.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ci/docker/utils.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ci/github/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ci/github/api.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ci/github/bootstrap.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ci/github/cache.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ci/github/cli.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ci/github/client.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ci/github/env.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ci/github/inject.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ci/inject.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ci/requirements.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ci/shell.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ci/utils.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/classdot.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cli/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cli/__main__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cli/_pathhack.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cli/clicli.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cli/install.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cli/main.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cli/managers.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cli/types.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/clipboard/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/clipboard/clipboard.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/clipboard/darwin_cf.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/clipboard/linux_x11.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/cmake.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/dataserver/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/dataserver/handlers.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/dataserver/http.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/dataserver/routes.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/dataserver/server.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/dataserver/targets.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/findimports.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/git/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/git/revisions.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/git/shallow.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/git/status.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/home/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/home/paths.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/home/secrets.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/home/shadow.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/imgur.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/interp/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/interp/__main__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/interp/cli.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/interp/default.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/interp/inject.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/interp/inspect.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/interp/providers/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/interp/providers/base.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/interp/providers/inject.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/interp/providers/running.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/interp/providers/standalone.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/interp/providers/system.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/interp/pyenv/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/interp/pyenv/inject.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/interp/pyenv/install.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/interp/pyenv/provider.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/interp/pyenv/pyenv.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/interp/resolvers.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/interp/types.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/interp/uv/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/interp/uv/inject.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/interp/uv/provider.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/interp/uv/uv.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/interp/venvs.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/magic/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/magic/__main__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/magic/cli.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/magic/find.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/magic/magic.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/magic/prepare.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/magic/styles.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/manifests/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/manifests/__main__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/manifests/build.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/manifests/dumping.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/manifests/main.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/mypy/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/mypy/debug.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/oci/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/oci/building.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/oci/compression.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/oci/data.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/oci/datarefs.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/oci/dataserver.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/oci/loading.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/oci/media.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/oci/pack/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/oci/pack/packing.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/oci/pack/repositories.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/oci/pack/unpacking.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/oci/repositories.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/packaging/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/packaging/marshal.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/packaging/names.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/packaging/requires.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/packaging/revisions.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/packaging/specifiers.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/packaging/versions.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/packaging/wheelfile.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/pip.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/precheck/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/precheck/__main__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/precheck/base.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/precheck/git.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/precheck/lite.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/precheck/main.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/precheck/manifests.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/precheck/scripts.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ptk/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ptk/apps/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/ptk/apps/ncdu.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/pycharm/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/pycharm/__main__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/pycharm/cli.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/pyproject/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/pyproject/__main__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/pyproject/cexts.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/pyproject/cli.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/pyproject/configs.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/pyproject/inject.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/pyproject/pkg.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/pyproject/reqs.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/pyproject/resources/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/pyproject/resources/docker-dev.sh +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/pyproject/resources/python.sh +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/pyproject/venvs.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/scripts/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/scripts/bumpversion.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/scripts/execrss.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/scripts/exectime.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/scripts/importtrace.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/scripts/interp.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/scripts/pyproject.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/scripts/slowcat.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/scripts/tmpexec.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tagstrings.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tokens/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tokens/all.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tokens/tokenizert.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tokens/utils.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tools/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tools/cloc.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tools/doc.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tools/docker.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tools/git/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tools/git/__main__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tools/git/cli.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tools/git/consts.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tools/git/messages.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tools/importscan.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tools/json/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tools/json/__main__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tools/json/cli.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tools/json/formats.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tools/json/io.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tools/json/processing.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tools/json/rendering.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tools/linehisto.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tools/mkenv.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tools/mkrelimp.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tools/notebook.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tools/pawk/__init__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tools/pawk/__main__.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tools/pawk/pawk.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tools/pip.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tools/prof.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tools/qr.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tools/shadow.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev/tools/sqlrepl.py +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev.egg-info/SOURCES.txt +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev.egg-info/dependency_links.txt +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev.egg-info/entry_points.txt +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/omdev.egg-info/top_level.txt +0 -0
- {omdev-0.0.0.dev241 → omdev-0.0.0.dev243}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: omdev
|
3
|
-
Version: 0.0.0.
|
3
|
+
Version: 0.0.0.dev243
|
4
4
|
Summary: omdev
|
5
5
|
Author: wrmsr
|
6
6
|
License: BSD-3-Clause
|
@@ -12,7 +12,7 @@ Classifier: Operating System :: OS Independent
|
|
12
12
|
Classifier: Operating System :: POSIX
|
13
13
|
Requires-Python: >=3.12
|
14
14
|
License-File: LICENSE
|
15
|
-
Requires-Dist: omlish==0.0.0.
|
15
|
+
Requires-Dist: omlish==0.0.0.dev243
|
16
16
|
Provides-Extra: all
|
17
17
|
Requires-Dist: black~=25.1; extra == "all"
|
18
18
|
Requires-Dist: pycparser~=2.22; extra == "all"
|
@@ -17,6 +17,7 @@ from .compose import get_compose_service_dependencies
|
|
17
17
|
from .docker.buildcaching import DockerBuildCaching
|
18
18
|
from .docker.cache import DockerCacheKey
|
19
19
|
from .docker.cmds import build_docker_image
|
20
|
+
from .docker.cmds import ensure_docker_image_setup
|
20
21
|
from .docker.imagepulling import DockerImagePulling
|
21
22
|
from .docker.utils import build_docker_file_hash
|
22
23
|
from .requirements import build_requirements_hash
|
@@ -51,6 +52,8 @@ class Ci(AsyncExitStacked):
|
|
51
52
|
|
52
53
|
no_dependencies: bool = False
|
53
54
|
|
55
|
+
setup_only: bool = False
|
56
|
+
|
54
57
|
run_options: ta.Optional[ta.Sequence[str]] = None
|
55
58
|
|
56
59
|
#
|
@@ -174,18 +177,21 @@ class Ci(AsyncExitStacked):
|
|
174
177
|
#
|
175
178
|
|
176
179
|
@cached_nullary
|
177
|
-
def
|
180
|
+
def get_dependency_images(self) -> ta.Sequence[str]:
|
178
181
|
deps = get_compose_service_dependencies(
|
179
182
|
self._config.compose_file,
|
180
183
|
self._config.service,
|
181
184
|
)
|
185
|
+
return sorted(deps.values())
|
182
186
|
|
187
|
+
@cached_nullary
|
188
|
+
def pull_dependencies_funcs(self) -> ta.Sequence[ta.Callable[[], ta.Awaitable]]:
|
183
189
|
return [
|
184
190
|
async_cached_nullary(functools.partial(
|
185
191
|
self._docker_image_pulling.pull_docker_image,
|
186
192
|
dep_image,
|
187
193
|
))
|
188
|
-
for dep_image in
|
194
|
+
for dep_image in self.get_dependency_images()
|
189
195
|
]
|
190
196
|
|
191
197
|
#
|
@@ -233,7 +239,26 @@ class Ci(AsyncExitStacked):
|
|
233
239
|
|
234
240
|
#
|
235
241
|
|
242
|
+
async def _run_setup_only(self) -> None:
|
243
|
+
image_ids = [
|
244
|
+
await self.resolve_ci_image(),
|
245
|
+
|
246
|
+
*(self.get_dependency_images() if not self._config.no_dependencies else []),
|
247
|
+
]
|
248
|
+
|
249
|
+
for image_id in image_ids:
|
250
|
+
with log_timing_context(f'Run setup only: {image_id}'):
|
251
|
+
await ensure_docker_image_setup(
|
252
|
+
image_id,
|
253
|
+
cwd=self._config.project_dir,
|
254
|
+
)
|
255
|
+
|
256
|
+
#
|
257
|
+
|
236
258
|
async def run(self) -> None:
|
237
259
|
await self.setup()
|
238
260
|
|
239
|
-
|
261
|
+
if self._config.setup_only:
|
262
|
+
await self._run_setup_only()
|
263
|
+
else:
|
264
|
+
await self._run_compose()
|
@@ -97,6 +97,8 @@ class CiCli(ArgparseCli):
|
|
97
97
|
|
98
98
|
argparse_arg('--no-dependencies', action='store_true'),
|
99
99
|
|
100
|
+
argparse_arg('--setup-only', action='store_true'),
|
101
|
+
|
100
102
|
argparse_arg('-e', '--env', action='append'),
|
101
103
|
argparse_arg('-v', '--volume', action='append'),
|
102
104
|
|
@@ -211,6 +213,8 @@ class CiCli(ArgparseCli):
|
|
211
213
|
|
212
214
|
no_dependencies=self.args.no_dependencies,
|
213
215
|
|
216
|
+
setup_only=self.args.setup_only,
|
217
|
+
|
214
218
|
run_options=run_options,
|
215
219
|
)
|
216
220
|
|
@@ -6,6 +6,7 @@ import json
|
|
6
6
|
import os.path
|
7
7
|
import typing as ta
|
8
8
|
|
9
|
+
from omlish.asyncs.asyncio.sockets import asyncio_wait_until_can_connect
|
9
10
|
from omlish.asyncs.asyncio.subprocesses import asyncio_subprocesses
|
10
11
|
from omlish.lite.check import check
|
11
12
|
from omlish.lite.json import json_dumps_compact
|
@@ -126,17 +127,14 @@ class CacheServedDockerCache(DockerCache):
|
|
126
127
|
dds_run_task = asyncio.create_task(dds.run())
|
127
128
|
try:
|
128
129
|
timeout = Timeout.of(self._config.server_start_timeout)
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
await asyncio.wait_for(writer.wait_closed(), timeout=timeout.remaining())
|
138
|
-
break
|
139
|
-
await asyncio.sleep(self._config.server_start_sleep)
|
130
|
+
|
131
|
+
await asyncio_wait_until_can_connect(
|
132
|
+
'localhost',
|
133
|
+
self._config.port,
|
134
|
+
timeout=timeout,
|
135
|
+
on_fail=lambda _: log.exception('Failed to connect to cache server - will try again'),
|
136
|
+
sleep_s=self._config.server_start_sleep,
|
137
|
+
)
|
140
138
|
|
141
139
|
if (prc := self._config.pull_run_cmd) is not None:
|
142
140
|
pull_cmd = [
|
@@ -123,3 +123,21 @@ async def load_docker_tar(
|
|
123
123
|
tar_file: str,
|
124
124
|
) -> str:
|
125
125
|
return await load_docker_tar_cmd(ShellCmd(f'cat {shlex.quote(tar_file)}'))
|
126
|
+
|
127
|
+
|
128
|
+
##
|
129
|
+
|
130
|
+
|
131
|
+
async def ensure_docker_image_setup(
|
132
|
+
image: str,
|
133
|
+
*,
|
134
|
+
cwd: ta.Optional[str] = None,
|
135
|
+
) -> None:
|
136
|
+
await asyncio_subprocesses.check_call(
|
137
|
+
'docker',
|
138
|
+
'run',
|
139
|
+
'--rm',
|
140
|
+
'--entrypoint', '/bin/true', # FIXME: lol
|
141
|
+
image,
|
142
|
+
**(dict(cwd=cwd) if cwd is not None else {}),
|
143
|
+
)
|
@@ -79,11 +79,7 @@ class OciDataTarWriter(ExitStacked):
|
|
79
79
|
tar_sha256=self._tw.sha256(),
|
80
80
|
)
|
81
81
|
|
82
|
-
def
|
83
|
-
super().__enter__()
|
84
|
-
|
85
|
-
#
|
86
|
-
|
82
|
+
def _enter_contexts(self) -> None:
|
87
83
|
self._cw = self._FileWrapper(self._f)
|
88
84
|
|
89
85
|
if self._compression is OciCompression.GZIP:
|
@@ -112,16 +108,12 @@ class OciDataTarWriter(ExitStacked):
|
|
112
108
|
self._tw = self._FileWrapper(self._cf)
|
113
109
|
|
114
110
|
self._tf = self._enter_context(
|
115
|
-
tarfile.open( # type: ignore
|
111
|
+
tarfile.open( # type: ignore # noqa
|
116
112
|
fileobj=self._tw,
|
117
113
|
mode='w',
|
118
114
|
),
|
119
115
|
)
|
120
116
|
|
121
|
-
#
|
122
|
-
|
123
|
-
return self
|
124
|
-
|
125
117
|
def tar_file(self) -> tarfile.TarFile:
|
126
118
|
return self._tf
|
127
119
|
|
@@ -2607,6 +2607,48 @@ class ArgparseCli:
|
|
2607
2607
|
return fn()
|
2608
2608
|
|
2609
2609
|
|
2610
|
+
########################################
|
2611
|
+
# ../../../omlish/asyncs/asyncio/sockets.py
|
2612
|
+
|
2613
|
+
|
2614
|
+
async def asyncio_wait_until_can_connect(
|
2615
|
+
host: ta.Any = None,
|
2616
|
+
port: ta.Any = None,
|
2617
|
+
*,
|
2618
|
+
timeout: ta.Optional[TimeoutLike] = None,
|
2619
|
+
on_fail: ta.Optional[ta.Callable[[BaseException], None]] = None,
|
2620
|
+
sleep_s: float = .1,
|
2621
|
+
exception: ta.Union[ta.Type[BaseException], ta.Tuple[ta.Type[BaseException], ...]] = (Exception,),
|
2622
|
+
) -> None:
|
2623
|
+
timeout = Timeout.of(timeout)
|
2624
|
+
|
2625
|
+
async def inner():
|
2626
|
+
while True:
|
2627
|
+
timeout()
|
2628
|
+
|
2629
|
+
try:
|
2630
|
+
reader, writer = await asyncio.open_connection(host, port)
|
2631
|
+
|
2632
|
+
except asyncio.CancelledError:
|
2633
|
+
raise
|
2634
|
+
|
2635
|
+
except exception as e: # noqa
|
2636
|
+
if on_fail is not None:
|
2637
|
+
on_fail(e)
|
2638
|
+
|
2639
|
+
else:
|
2640
|
+
writer.close()
|
2641
|
+
await asyncio.wait_for(writer.wait_closed(), timeout=timeout.or_(None))
|
2642
|
+
break
|
2643
|
+
|
2644
|
+
await asyncio.sleep(min(sleep_s, timeout.remaining()))
|
2645
|
+
|
2646
|
+
if timeout() != float('inf'):
|
2647
|
+
await asyncio.wait_for(inner(), timeout=timeout())
|
2648
|
+
else:
|
2649
|
+
await inner()
|
2650
|
+
|
2651
|
+
|
2610
2652
|
########################################
|
2611
2653
|
# ../../../omlish/asyncs/asyncio/timeouts.py
|
2612
2654
|
|
@@ -3041,20 +3083,64 @@ class HttpRequestParser:
|
|
3041
3083
|
|
3042
3084
|
|
3043
3085
|
class ExitStacked:
|
3086
|
+
def __init_subclass__(cls, **kwargs: ta.Any) -> None:
|
3087
|
+
super().__init_subclass__(**kwargs)
|
3088
|
+
|
3089
|
+
for a in ('__enter__', '__exit__'):
|
3090
|
+
for b in cls.__bases__:
|
3091
|
+
if b is ExitStacked:
|
3092
|
+
continue
|
3093
|
+
try:
|
3094
|
+
fn = getattr(b, a)
|
3095
|
+
except AttributeError:
|
3096
|
+
pass
|
3097
|
+
else:
|
3098
|
+
if fn is not getattr(ExitStacked, a):
|
3099
|
+
raise TypeError(f'ExitStacked subclass {cls} must not not override {a} via {b}')
|
3100
|
+
|
3044
3101
|
_exit_stack: ta.Optional[contextlib.ExitStack] = None
|
3045
3102
|
|
3103
|
+
@contextlib.contextmanager
|
3104
|
+
def _exit_stacked_init_wrapper(self) -> ta.Iterator[None]:
|
3105
|
+
"""
|
3106
|
+
Overridable wrapper around __enter__ which deliberately does not have access to an _exit_stack yet. Intended for
|
3107
|
+
things like wrapping __enter__ in a lock.
|
3108
|
+
"""
|
3109
|
+
|
3110
|
+
yield
|
3111
|
+
|
3112
|
+
@ta.final
|
3046
3113
|
def __enter__(self: ExitStackedT) -> ExitStackedT:
|
3047
|
-
|
3048
|
-
|
3049
|
-
|
3050
|
-
|
3114
|
+
"""
|
3115
|
+
Final because any contexts entered during this init must be exited if any exception is thrown, and user
|
3116
|
+
overriding would likely interfere with that. Override `_enter_contexts` for such init.
|
3117
|
+
"""
|
3118
|
+
|
3119
|
+
with self._exit_stacked_init_wrapper():
|
3120
|
+
check.state(self._exit_stack is None)
|
3121
|
+
es = self._exit_stack = contextlib.ExitStack()
|
3122
|
+
es.__enter__()
|
3123
|
+
try:
|
3124
|
+
self._enter_contexts()
|
3125
|
+
except Exception: # noqa
|
3126
|
+
es.__exit__(*sys.exc_info())
|
3127
|
+
raise
|
3128
|
+
return self
|
3051
3129
|
|
3130
|
+
@ta.final
|
3052
3131
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
3053
3132
|
if (es := self._exit_stack) is None:
|
3054
3133
|
return None
|
3055
|
-
|
3134
|
+
try:
|
3135
|
+
self._exit_contexts()
|
3136
|
+
except Exception: # noqa
|
3137
|
+
es.__exit__(*sys.exc_info())
|
3138
|
+
raise
|
3056
3139
|
return es.__exit__(exc_type, exc_val, exc_tb)
|
3057
3140
|
|
3141
|
+
def _enter_contexts(self) -> None:
|
3142
|
+
pass
|
3143
|
+
|
3058
3144
|
def _exit_contexts(self) -> None:
|
3059
3145
|
pass
|
3060
3146
|
|
@@ -3064,20 +3150,54 @@ class ExitStacked:
|
|
3064
3150
|
|
3065
3151
|
|
3066
3152
|
class AsyncExitStacked:
|
3153
|
+
def __init_subclass__(cls, **kwargs: ta.Any) -> None:
|
3154
|
+
super().__init_subclass__(**kwargs)
|
3155
|
+
|
3156
|
+
for a in ('__aenter__', '__aexit__'):
|
3157
|
+
for b in cls.__bases__:
|
3158
|
+
if b is AsyncExitStacked:
|
3159
|
+
continue
|
3160
|
+
try:
|
3161
|
+
fn = getattr(b, a)
|
3162
|
+
except AttributeError:
|
3163
|
+
pass
|
3164
|
+
else:
|
3165
|
+
if fn is not getattr(AsyncExitStacked, a):
|
3166
|
+
raise TypeError(f'AsyncExitStacked subclass {cls} must not not override {a} via {b}')
|
3167
|
+
|
3067
3168
|
_exit_stack: ta.Optional[contextlib.AsyncExitStack] = None
|
3068
3169
|
|
3170
|
+
@contextlib.asynccontextmanager
|
3171
|
+
async def _async_exit_stacked_init_wrapper(self) -> ta.AsyncGenerator[None, None]:
|
3172
|
+
yield
|
3173
|
+
|
3174
|
+
@ta.final
|
3069
3175
|
async def __aenter__(self: AsyncExitStackedT) -> AsyncExitStackedT:
|
3070
|
-
|
3071
|
-
|
3072
|
-
|
3073
|
-
|
3176
|
+
async with self._async_exit_stacked_init_wrapper():
|
3177
|
+
check.state(self._exit_stack is None)
|
3178
|
+
es = self._exit_stack = contextlib.AsyncExitStack()
|
3179
|
+
await es.__aenter__()
|
3180
|
+
try:
|
3181
|
+
await self._async_enter_contexts()
|
3182
|
+
except Exception: # noqa
|
3183
|
+
await es.__aexit__(*sys.exc_info())
|
3184
|
+
raise
|
3185
|
+
return self
|
3074
3186
|
|
3187
|
+
@ta.final
|
3075
3188
|
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
3076
3189
|
if (es := self._exit_stack) is None:
|
3077
3190
|
return None
|
3078
|
-
|
3191
|
+
try:
|
3192
|
+
await self._async_exit_contexts()
|
3193
|
+
except Exception: # noqa
|
3194
|
+
await es.__aexit__(*sys.exc_info())
|
3195
|
+
raise
|
3079
3196
|
return await es.__aexit__(exc_type, exc_val, exc_tb)
|
3080
3197
|
|
3198
|
+
async def _async_enter_contexts(self) -> None:
|
3199
|
+
pass
|
3200
|
+
|
3081
3201
|
async def _async_exit_contexts(self) -> None:
|
3082
3202
|
pass
|
3083
3203
|
|
@@ -6952,11 +7072,7 @@ class OciDataTarWriter(ExitStacked):
|
|
6952
7072
|
tar_sha256=self._tw.sha256(),
|
6953
7073
|
)
|
6954
7074
|
|
6955
|
-
def
|
6956
|
-
super().__enter__()
|
6957
|
-
|
6958
|
-
#
|
6959
|
-
|
7075
|
+
def _enter_contexts(self) -> None:
|
6960
7076
|
self._cw = self._FileWrapper(self._f)
|
6961
7077
|
|
6962
7078
|
if self._compression is OciCompression.GZIP:
|
@@ -6985,16 +7101,12 @@ class OciDataTarWriter(ExitStacked):
|
|
6985
7101
|
self._tw = self._FileWrapper(self._cf)
|
6986
7102
|
|
6987
7103
|
self._tf = self._enter_context(
|
6988
|
-
tarfile.open( # type: ignore
|
7104
|
+
tarfile.open( # type: ignore # noqa
|
6989
7105
|
fileobj=self._tw,
|
6990
7106
|
mode='w',
|
6991
7107
|
),
|
6992
7108
|
)
|
6993
7109
|
|
6994
|
-
#
|
6995
|
-
|
6996
|
-
return self
|
6997
|
-
|
6998
7110
|
def tar_file(self) -> tarfile.TarFile:
|
6999
7111
|
return self._tf
|
7000
7112
|
|
@@ -8800,58 +8912,88 @@ class SocketServer(abc.ABC):
|
|
8800
8912
|
|
8801
8913
|
#
|
8802
8914
|
|
8803
|
-
|
8804
|
-
|
8805
|
-
|
8806
|
-
|
8807
|
-
|
8915
|
+
class PollResult(enum.Enum):
|
8916
|
+
TIMEOUT = enum.auto()
|
8917
|
+
CONNECTION = enum.auto()
|
8918
|
+
ERROR = enum.auto()
|
8919
|
+
SHUTDOWN = enum.auto()
|
8808
8920
|
|
8809
|
-
|
8921
|
+
class PollContext(ExitStacked, abc.ABC):
|
8922
|
+
@abc.abstractmethod
|
8923
|
+
def poll(self, timeout: ta.Optional[float] = None) -> 'SocketServer.PollResult':
|
8924
|
+
raise NotImplementedError
|
8810
8925
|
|
8811
|
-
|
8812
|
-
|
8813
|
-
|
8814
|
-
# polling. Polling reduces our responsiveness to a shutdown request and wastes cpu at all other times.
|
8815
|
-
with self.Selector() as selector:
|
8816
|
-
selector.register(self._binder.fileno(), selectors.EVENT_READ)
|
8926
|
+
class _PollContext(PollContext):
|
8927
|
+
def __init__(self, server: 'SocketServer') -> None:
|
8928
|
+
super().__init__()
|
8817
8929
|
|
8818
|
-
|
8930
|
+
self._server = server
|
8819
8931
|
|
8820
|
-
|
8821
|
-
self._is_shutdown.set()
|
8932
|
+
_selector: ta.Any = None
|
8822
8933
|
|
8823
|
-
|
8824
|
-
|
8825
|
-
|
8826
|
-
poll_interval = self._poll_interval
|
8934
|
+
def _enter_contexts(self) -> None:
|
8935
|
+
self._enter_context(self._server._lock) # noqa: SLF001
|
8936
|
+
self._enter_context(self._server._binder) # noqa: SLF001
|
8827
8937
|
|
8828
|
-
|
8829
|
-
|
8830
|
-
|
8831
|
-
|
8938
|
+
self._server._binder.listen() # noqa: SLF001
|
8939
|
+
|
8940
|
+
self._server._is_shutdown.clear() # noqa: SLF001
|
8941
|
+
self._enter_context(defer(self._server._is_shutdown.set)) # noqa
|
8942
|
+
|
8943
|
+
# XXX: Consider using another file descriptor or connecting to the socket to wake this up instead of
|
8944
|
+
# polling. Polling reduces our responsiveness to a shutdown request and wastes cpu at all other times.
|
8945
|
+
self._selector = self._enter_context(self._server.Selector())
|
8946
|
+
self._selector.register(self._server._binder.fileno(), selectors.EVENT_READ) # noqa: SLF001
|
8947
|
+
|
8948
|
+
def poll(self, timeout: ta.Optional[float] = None) -> 'SocketServer.PollResult':
|
8949
|
+
if self._server._should_shutdown: # noqa: SLF001
|
8950
|
+
return SocketServer.PollResult.SHUTDOWN
|
8832
8951
|
|
8833
|
-
|
8834
|
-
if self._should_shutdown:
|
8835
|
-
break # type: ignore[unreachable]
|
8952
|
+
ready = self._selector.select(timeout)
|
8836
8953
|
|
8837
|
-
|
8838
|
-
|
8839
|
-
|
8954
|
+
# bpo-35017: shutdown() called during select(), exit immediately.
|
8955
|
+
if self._server._should_shutdown: # noqa: SLF001
|
8956
|
+
return SocketServer.PollResult.SHUTDOWN # type: ignore[unreachable]
|
8840
8957
|
|
8841
|
-
|
8842
|
-
|
8958
|
+
if not ready:
|
8959
|
+
return SocketServer.PollResult.TIMEOUT
|
8843
8960
|
|
8844
|
-
|
8961
|
+
try:
|
8962
|
+
conn = self._server._binder.accept() # noqa: SLF001
|
8963
|
+
|
8964
|
+
except OSError as exc:
|
8965
|
+
self._server._handle_error(exc) # noqa: SLF001
|
8966
|
+
|
8967
|
+
return SocketServer.PollResult.ERROR
|
8968
|
+
|
8969
|
+
try:
|
8970
|
+
self._server._handler(conn) # noqa: SLF001
|
8845
8971
|
|
8846
|
-
|
8847
|
-
|
8972
|
+
except Exception as exc: # noqa
|
8973
|
+
self._server._handle_error(exc, conn) # noqa: SLF001
|
8848
8974
|
|
8849
|
-
|
8850
|
-
self._handle_error(exc, conn)
|
8975
|
+
close_socket_immediately(conn.socket)
|
8851
8976
|
|
8852
|
-
|
8977
|
+
return SocketServer.PollResult.CONNECTION
|
8853
8978
|
|
8854
|
-
|
8979
|
+
def poll_context(self) -> PollContext:
|
8980
|
+
return self._PollContext(self)
|
8981
|
+
|
8982
|
+
#
|
8983
|
+
|
8984
|
+
@contextlib.contextmanager
|
8985
|
+
def loop_context(self, poll_interval: ta.Optional[float] = None) -> ta.Iterator[ta.Iterator[bool]]:
|
8986
|
+
if poll_interval is None:
|
8987
|
+
poll_interval = self._poll_interval
|
8988
|
+
|
8989
|
+
with self.poll_context() as pc:
|
8990
|
+
def loop():
|
8991
|
+
while True:
|
8992
|
+
res = pc.poll(poll_interval)
|
8993
|
+
if res in (SocketServer.PollResult.ERROR, SocketServer.PollResult.SHUTDOWN):
|
8994
|
+
return
|
8995
|
+
else:
|
8996
|
+
yield res == SocketServer.PollResult.CONNECTION
|
8855
8997
|
|
8856
8998
|
yield loop()
|
8857
8999
|
|
@@ -10983,6 +11125,24 @@ async def load_docker_tar(
|
|
10983
11125
|
return await load_docker_tar_cmd(ShellCmd(f'cat {shlex.quote(tar_file)}'))
|
10984
11126
|
|
10985
11127
|
|
11128
|
+
##
|
11129
|
+
|
11130
|
+
|
11131
|
+
async def ensure_docker_image_setup(
|
11132
|
+
image: str,
|
11133
|
+
*,
|
11134
|
+
cwd: ta.Optional[str] = None,
|
11135
|
+
) -> None:
|
11136
|
+
await asyncio_subprocesses.check_call(
|
11137
|
+
'docker',
|
11138
|
+
'run',
|
11139
|
+
'--rm',
|
11140
|
+
'--entrypoint', '/bin/true', # FIXME: lol
|
11141
|
+
image,
|
11142
|
+
**(dict(cwd=cwd) if cwd is not None else {}),
|
11143
|
+
)
|
11144
|
+
|
11145
|
+
|
10986
11146
|
########################################
|
10987
11147
|
# ../docker/dataserver.py
|
10988
11148
|
|
@@ -11442,17 +11602,14 @@ class CacheServedDockerCache(DockerCache):
|
|
11442
11602
|
dds_run_task = asyncio.create_task(dds.run())
|
11443
11603
|
try:
|
11444
11604
|
timeout = Timeout.of(self._config.server_start_timeout)
|
11445
|
-
|
11446
|
-
|
11447
|
-
|
11448
|
-
|
11449
|
-
|
11450
|
-
|
11451
|
-
|
11452
|
-
|
11453
|
-
await asyncio.wait_for(writer.wait_closed(), timeout=timeout.remaining())
|
11454
|
-
break
|
11455
|
-
await asyncio.sleep(self._config.server_start_sleep)
|
11605
|
+
|
11606
|
+
await asyncio_wait_until_can_connect(
|
11607
|
+
'localhost',
|
11608
|
+
self._config.port,
|
11609
|
+
timeout=timeout,
|
11610
|
+
on_fail=lambda _: log.exception('Failed to connect to cache server - will try again'),
|
11611
|
+
sleep_s=self._config.server_start_sleep,
|
11612
|
+
)
|
11456
11613
|
|
11457
11614
|
if (prc := self._config.pull_run_cmd) is not None:
|
11458
11615
|
pull_cmd = [
|
@@ -11613,6 +11770,8 @@ class Ci(AsyncExitStacked):
|
|
11613
11770
|
|
11614
11771
|
no_dependencies: bool = False
|
11615
11772
|
|
11773
|
+
setup_only: bool = False
|
11774
|
+
|
11616
11775
|
run_options: ta.Optional[ta.Sequence[str]] = None
|
11617
11776
|
|
11618
11777
|
#
|
@@ -11736,18 +11895,21 @@ class Ci(AsyncExitStacked):
|
|
11736
11895
|
#
|
11737
11896
|
|
11738
11897
|
@cached_nullary
|
11739
|
-
def
|
11898
|
+
def get_dependency_images(self) -> ta.Sequence[str]:
|
11740
11899
|
deps = get_compose_service_dependencies(
|
11741
11900
|
self._config.compose_file,
|
11742
11901
|
self._config.service,
|
11743
11902
|
)
|
11903
|
+
return sorted(deps.values())
|
11744
11904
|
|
11905
|
+
@cached_nullary
|
11906
|
+
def pull_dependencies_funcs(self) -> ta.Sequence[ta.Callable[[], ta.Awaitable]]:
|
11745
11907
|
return [
|
11746
11908
|
async_cached_nullary(functools.partial(
|
11747
11909
|
self._docker_image_pulling.pull_docker_image,
|
11748
11910
|
dep_image,
|
11749
11911
|
))
|
11750
|
-
for dep_image in
|
11912
|
+
for dep_image in self.get_dependency_images()
|
11751
11913
|
]
|
11752
11914
|
|
11753
11915
|
#
|
@@ -11795,10 +11957,29 @@ class Ci(AsyncExitStacked):
|
|
11795
11957
|
|
11796
11958
|
#
|
11797
11959
|
|
11960
|
+
async def _run_setup_only(self) -> None:
|
11961
|
+
image_ids = [
|
11962
|
+
await self.resolve_ci_image(),
|
11963
|
+
|
11964
|
+
*(self.get_dependency_images() if not self._config.no_dependencies else []),
|
11965
|
+
]
|
11966
|
+
|
11967
|
+
for image_id in image_ids:
|
11968
|
+
with log_timing_context(f'Run setup only: {image_id}'):
|
11969
|
+
await ensure_docker_image_setup(
|
11970
|
+
image_id,
|
11971
|
+
cwd=self._config.project_dir,
|
11972
|
+
)
|
11973
|
+
|
11974
|
+
#
|
11975
|
+
|
11798
11976
|
async def run(self) -> None:
|
11799
11977
|
await self.setup()
|
11800
11978
|
|
11801
|
-
|
11979
|
+
if self._config.setup_only:
|
11980
|
+
await self._run_setup_only()
|
11981
|
+
else:
|
11982
|
+
await self._run_compose()
|
11802
11983
|
|
11803
11984
|
|
11804
11985
|
########################################
|
@@ -11979,6 +12160,8 @@ class CiCli(ArgparseCli):
|
|
11979
12160
|
|
11980
12161
|
argparse_arg('--no-dependencies', action='store_true'),
|
11981
12162
|
|
12163
|
+
argparse_arg('--setup-only', action='store_true'),
|
12164
|
+
|
11982
12165
|
argparse_arg('-e', '--env', action='append'),
|
11983
12166
|
argparse_arg('-v', '--volume', action='append'),
|
11984
12167
|
|
@@ -12093,6 +12276,8 @@ class CiCli(ArgparseCli):
|
|
12093
12276
|
|
12094
12277
|
no_dependencies=self.args.no_dependencies,
|
12095
12278
|
|
12279
|
+
setup_only=self.args.setup_only,
|
12280
|
+
|
12096
12281
|
run_options=run_options,
|
12097
12282
|
)
|
12098
12283
|
|
@@ -55,10 +55,8 @@ class DelimitingParser:
|
|
55
55
|
class StreamBuilder(lang.ExitStacked):
|
56
56
|
_builder: JsonObjectBuilder | None = None
|
57
57
|
|
58
|
-
def
|
59
|
-
super().__enter__()
|
58
|
+
def _enter_contexts(self) -> None:
|
60
59
|
self._builder = self._enter_context(JsonObjectBuilder())
|
61
|
-
return self
|
62
60
|
|
63
61
|
def build(self, e: JsonStreamParserEvent) -> ta.Generator[ta.Any, None, None]:
|
64
62
|
yield from check.not_none(self._builder)(e)
|
@@ -69,12 +67,10 @@ class StreamParser(lang.ExitStacked):
|
|
69
67
|
_lex: JsonStreamLexer
|
70
68
|
_parse: JsonStreamParser
|
71
69
|
|
72
|
-
def
|
73
|
-
super().__enter__()
|
70
|
+
def _enter_contexts(self) -> None:
|
74
71
|
self._decoder = codecs.getincrementaldecoder('utf-8')()
|
75
72
|
self._lex = self._enter_context(JsonStreamLexer())
|
76
73
|
self._parse = self._enter_context(JsonStreamParser())
|
77
|
-
return self
|
78
74
|
|
79
75
|
def parse(self, b: bytes) -> ta.Generator[JsonStreamParserEvent, None, None]:
|
80
76
|
for s in self._decoder.decode(b, not b):
|