omdev 0.0.0.dev289__tar.gz → 0.0.0.dev290__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.dev289/omdev.egg-info → omdev-0.0.0.dev290}/PKG-INFO +2 -2
- omdev-0.0.0.dev289/omdev/ci/github/client.py → omdev-0.0.0.dev290/omdev/ci/github/api/clients.py +172 -209
- {omdev-0.0.0.dev289/omdev/ci/github → omdev-0.0.0.dev290/omdev/ci/github/api/v1}/api.py +5 -87
- omdev-0.0.0.dev290/omdev/ci/github/api/v1/client.py +171 -0
- omdev-0.0.0.dev290/omdev/ci/github/api/v2/api.py +148 -0
- omdev-0.0.0.dev290/omdev/ci/github/api/v2/client.py +166 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/ci/github/cache.py +14 -3
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/ci/github/cli.py +1 -1
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/scripts/ci.py +663 -288
- omdev-0.0.0.dev290/omdev/tools/git/__init__.py +0 -0
- omdev-0.0.0.dev290/omdev/tools/json/__init__.py +0 -0
- omdev-0.0.0.dev290/omdev/tools/pawk/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290/omdev.egg-info}/PKG-INFO +2 -2
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev.egg-info/SOURCES.txt +8 -2
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev.egg-info/requires.txt +1 -1
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/pyproject.toml +2 -2
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/LICENSE +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/MANIFEST.in +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/README.rst +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/.manifests.json +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/__about__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/amalg/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/amalg/__main__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/amalg/gen.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/amalg/imports.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/amalg/main.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/amalg/manifests.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/amalg/resources.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/amalg/srcfiles.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/amalg/strip.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/amalg/types.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/amalg/typing.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/antlr/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/antlr/consts.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/antlr/gen.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cache/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cache/compute/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cache/compute/cache.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cache/compute/contexts.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cache/compute/currents.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cache/compute/fns.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cache/compute/resolvers.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cache/compute/storage.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cache/compute/types.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cache/data/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cache/data/actions.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cache/data/cache.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cache/data/consts.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cache/data/defaults.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cache/data/manifests.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cache/data/specs.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cc/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cc/__main__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cc/cdeps.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cc/cdeps.toml +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cc/cli.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cexts/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cexts/_boilerplate.cc +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cexts/_distutils/LICENSE +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cexts/_distutils/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cexts/_distutils/build_ext.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cexts/_distutils/compilers/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cexts/_distutils/compilers/ccompiler.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cexts/_distutils/compilers/options.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cexts/_distutils/compilers/unixccompiler.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cexts/_distutils/dir_util.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cexts/_distutils/errors.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cexts/_distutils/extension.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cexts/_distutils/file_util.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cexts/_distutils/modified.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cexts/_distutils/spawn.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cexts/_distutils/sysconfig.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cexts/_distutils/util.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cexts/_distutils/version.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cexts/build.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cexts/cmake.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cexts/importhook.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cexts/magic.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cexts/scan.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/ci/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/ci/__main__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/ci/cache.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/ci/ci.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/ci/cli.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/ci/compose.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/ci/consts.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/ci/docker/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/ci/docker/buildcaching.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/ci/docker/cache.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/ci/docker/cacheserved/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/ci/docker/cacheserved/cache.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/ci/docker/cacheserved/manifests.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/ci/docker/cmds.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/ci/docker/dataserver.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/ci/docker/imagepulling.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/ci/docker/inject.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/ci/docker/packing.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/ci/docker/repositories.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/ci/docker/utils.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/ci/github/__init__.py +0 -0
- {omdev-0.0.0.dev289/omdev/clipboard → omdev-0.0.0.dev290/omdev/ci/github/api}/__init__.py +0 -0
- {omdev-0.0.0.dev289/omdev/git → omdev-0.0.0.dev290/omdev/ci/github/api/v1}/__init__.py +0 -0
- {omdev-0.0.0.dev289/omdev/home → omdev-0.0.0.dev290/omdev/ci/github/api/v2}/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/ci/github/bootstrap.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/ci/github/env.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/ci/github/inject.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/ci/inject.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/ci/requirements.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/ci/shell.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/ci/utils.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cli/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cli/__main__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cli/_pathhack.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cli/clicli.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cli/install.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cli/main.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cli/managers.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cli/types.py +0 -0
- {omdev-0.0.0.dev289/omdev/interp/providers → omdev-0.0.0.dev290/omdev/clipboard}/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/clipboard/clipboard.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/clipboard/darwin_cf.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/clipboard/linux_x11.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/cmake.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/dataserver/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/dataserver/handlers.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/dataserver/http.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/dataserver/routes.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/dataserver/server.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/dataserver/targets.py +0 -0
- {omdev-0.0.0.dev289/omdev/interp/pyenv → omdev-0.0.0.dev290/omdev/git}/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/git/magic.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/git/revisions.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/git/shallow.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/git/status.py +0 -0
- {omdev-0.0.0.dev289/omdev/interp/uv → omdev-0.0.0.dev290/omdev/home}/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/home/paths.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/home/secrets.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/home/shadow.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/imgur.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/interp/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/interp/__main__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/interp/cli.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/interp/default.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/interp/inject.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/interp/inspect.py +0 -0
- {omdev-0.0.0.dev289/omdev/mypy → omdev-0.0.0.dev290/omdev/interp/providers}/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/interp/providers/base.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/interp/providers/inject.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/interp/providers/running.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/interp/providers/standalone.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/interp/providers/system.py +0 -0
- {omdev-0.0.0.dev289/omdev/oci → omdev-0.0.0.dev290/omdev/interp/pyenv}/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/interp/pyenv/inject.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/interp/pyenv/install.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/interp/pyenv/provider.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/interp/pyenv/pyenv.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/interp/resolvers.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/interp/types.py +0 -0
- {omdev-0.0.0.dev289/omdev/oci/pack → omdev-0.0.0.dev290/omdev/interp/uv}/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/interp/uv/inject.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/interp/uv/provider.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/interp/uv/uv.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/interp/venvs.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/magic/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/magic/__main__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/magic/cli.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/magic/find.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/magic/magic.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/magic/prepare.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/magic/styles.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/manifests/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/manifests/__main__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/manifests/build.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/manifests/dumping.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/manifests/main.py +0 -0
- {omdev-0.0.0.dev289/omdev/packaging → omdev-0.0.0.dev290/omdev/mypy}/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/mypy/debug.py +0 -0
- {omdev-0.0.0.dev289/omdev/precheck → omdev-0.0.0.dev290/omdev/oci}/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/oci/building.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/oci/compression.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/oci/data.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/oci/datarefs.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/oci/dataserver.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/oci/loading.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/oci/media.py +0 -0
- {omdev-0.0.0.dev289/omdev/ptk/apps → omdev-0.0.0.dev290/omdev/oci/pack}/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/oci/pack/packing.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/oci/pack/repositories.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/oci/pack/unpacking.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/oci/repositories.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/oci/tars.py +0 -0
- {omdev-0.0.0.dev289/omdev/py/scripts → omdev-0.0.0.dev290/omdev/packaging}/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/packaging/marshal.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/packaging/names.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/packaging/requires.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/packaging/revisions.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/packaging/specifiers.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/packaging/versions.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/packaging/wheelfile.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/pip.py +0 -0
- {omdev-0.0.0.dev289/omdev/py/tools → omdev-0.0.0.dev290/omdev/precheck}/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/precheck/__main__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/precheck/base.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/precheck/git.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/precheck/lite.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/precheck/main.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/precheck/manifests.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/precheck/scripts.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/ptk/__init__.py +0 -0
- {omdev-0.0.0.dev289/omdev/pyproject/resources → omdev-0.0.0.dev290/omdev/ptk/apps}/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/ptk/apps/ncdu.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/py/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/py/attrdocs.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/py/bracepy.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/py/classdot.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/py/findimports.py +0 -0
- {omdev-0.0.0.dev289/omdev/tokens → omdev-0.0.0.dev290/omdev/py/scripts}/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/py/scripts/bumpversion.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/py/scripts/execstat.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/py/scripts/importtrace.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/py/srcheaders.py +0 -0
- {omdev-0.0.0.dev289/omdev/tools/git → omdev-0.0.0.dev290/omdev/py/tools}/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/py/tools/importscan.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/py/tools/mkrelimp.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/pyproject/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/pyproject/__main__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/pyproject/cexts.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/pyproject/cli.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/pyproject/configs.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/pyproject/inject.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/pyproject/pkg.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/pyproject/reqs.py +0 -0
- {omdev-0.0.0.dev289/omdev/tools/json → omdev-0.0.0.dev290/omdev/pyproject/resources}/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/pyproject/resources/docker-dev.sh +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/pyproject/resources/python.sh +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/pyproject/venvs.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/scripts/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/scripts/interp.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/scripts/pyproject.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/scripts/slowcat.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/scripts/tmpexec.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/tagstrings.py +0 -0
- {omdev-0.0.0.dev289/omdev/tools/pawk → omdev-0.0.0.dev290/omdev/tokens}/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/tokens/all.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/tokens/tokenizert.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/tokens/utils.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/tools/__init__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/tools/cloc.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/tools/diff.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/tools/doc.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/tools/docker.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/tools/git/__main__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/tools/git/cli.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/tools/git/consts.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/tools/git/messages.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/tools/intellij.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/tools/json/__main__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/tools/json/cli.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/tools/json/formats.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/tools/json/io.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/tools/json/parsing.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/tools/json/processing.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/tools/json/rendering.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/tools/linehisto.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/tools/mkenv.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/tools/notebook.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/tools/pawk/__main__.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/tools/pawk/pawk.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/tools/pip.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/tools/prof.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/tools/qr.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/tools/shadow.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev/tools/sqlrepl.py +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev.egg-info/dependency_links.txt +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev.egg-info/entry_points.txt +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/omdev.egg-info/top_level.txt +0 -0
- {omdev-0.0.0.dev289 → omdev-0.0.0.dev290}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: omdev
|
3
|
-
Version: 0.0.0.
|
3
|
+
Version: 0.0.0.dev290
|
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.dev290
|
16
16
|
Provides-Extra: all
|
17
17
|
Requires-Dist: black~=25.1; extra == "all"
|
18
18
|
Requires-Dist: pycparser~=2.22; extra == "all"
|
omdev-0.0.0.dev289/omdev/ci/github/client.py → omdev-0.0.0.dev290/omdev/ci/github/api/clients.py
RENAMED
@@ -1,8 +1,9 @@
|
|
1
|
-
# ruff: noqa:
|
1
|
+
# ruff: noqa: UP006 UP007
|
2
2
|
import abc
|
3
3
|
import asyncio
|
4
4
|
import dataclasses as dc
|
5
5
|
import http.client
|
6
|
+
import itertools
|
6
7
|
import json
|
7
8
|
import os
|
8
9
|
import typing as ta
|
@@ -10,20 +11,21 @@ import urllib.parse
|
|
10
11
|
import urllib.request
|
11
12
|
|
12
13
|
from omlish.asyncs.asyncio.utils import asyncio_wait_concurrent
|
14
|
+
from omlish.http.urllib import NonRaisingUrllibErrorProcessor
|
13
15
|
from omlish.lite.check import check
|
14
16
|
from omlish.lite.json import json_dumps_compact
|
15
17
|
from omlish.lite.logs import log
|
16
18
|
from omlish.lite.timing import log_timing_context
|
17
19
|
|
18
|
-
from
|
19
|
-
from
|
20
|
-
from .env import register_github_env_var
|
20
|
+
from ...consts import CI_CACHE_VERSION
|
21
|
+
from ..env import register_github_env_var
|
21
22
|
|
22
23
|
|
23
24
|
##
|
24
25
|
|
25
26
|
|
26
27
|
class GithubCacheClient(abc.ABC):
|
28
|
+
@dc.dataclass(frozen=True)
|
27
29
|
class Entry(abc.ABC): # noqa
|
28
30
|
pass
|
29
31
|
|
@@ -46,18 +48,21 @@ class GithubCacheClient(abc.ABC):
|
|
46
48
|
##
|
47
49
|
|
48
50
|
|
49
|
-
class
|
50
|
-
BASE_URL_ENV_VAR = register_github_env_var('ACTIONS_CACHE_URL')
|
51
|
+
class BaseGithubCacheClient(GithubCacheClient, abc.ABC):
|
51
52
|
AUTH_TOKEN_ENV_VAR = register_github_env_var('ACTIONS_RUNTIME_TOKEN') # noqa
|
52
53
|
|
53
54
|
KEY_SUFFIX_ENV_VAR = register_github_env_var('GITHUB_RUN_ID')
|
54
55
|
|
56
|
+
DEFAULT_CONCURRENCY = 4
|
57
|
+
DEFAULT_CHUNK_SIZE = 64 * 1024 * 1024
|
58
|
+
|
55
59
|
#
|
56
60
|
|
57
61
|
def __init__(
|
58
62
|
self,
|
59
63
|
*,
|
60
|
-
|
64
|
+
service_url: str,
|
65
|
+
|
61
66
|
auth_token: ta.Optional[str] = None,
|
62
67
|
|
63
68
|
key_prefix: ta.Optional[str] = None,
|
@@ -66,14 +71,15 @@ class GithubCacheServiceV1BaseClient(GithubCacheClient, abc.ABC):
|
|
66
71
|
cache_version: int = CI_CACHE_VERSION,
|
67
72
|
|
68
73
|
loop: ta.Optional[asyncio.AbstractEventLoop] = None,
|
74
|
+
|
75
|
+
concurrency: int = DEFAULT_CONCURRENCY,
|
76
|
+
chunk_size: int = DEFAULT_CHUNK_SIZE,
|
69
77
|
) -> None:
|
70
78
|
super().__init__()
|
71
79
|
|
72
80
|
#
|
73
81
|
|
74
|
-
|
75
|
-
base_url = check.non_empty_str(self.BASE_URL_ENV_VAR())
|
76
|
-
self._service_url = GithubCacheServiceV1.get_service_url(base_url)
|
82
|
+
self._service_url = check.non_empty_str(service_url)
|
77
83
|
|
78
84
|
if auth_token is None:
|
79
85
|
auth_token = self.AUTH_TOKEN_ENV_VAR()
|
@@ -95,7 +101,16 @@ class GithubCacheServiceV1BaseClient(GithubCacheClient, abc.ABC):
|
|
95
101
|
|
96
102
|
self._given_loop = loop
|
97
103
|
|
98
|
-
|
104
|
+
#
|
105
|
+
|
106
|
+
check.arg(concurrency > 0)
|
107
|
+
self._concurrency = concurrency
|
108
|
+
|
109
|
+
check.arg(chunk_size > 0)
|
110
|
+
self._chunk_size = chunk_size
|
111
|
+
|
112
|
+
##
|
113
|
+
# misc
|
99
114
|
|
100
115
|
def _get_loop(self) -> asyncio.AbstractEventLoop:
|
101
116
|
if (loop := self._given_loop) is not None:
|
@@ -104,21 +119,25 @@ class GithubCacheServiceV1BaseClient(GithubCacheClient, abc.ABC):
|
|
104
119
|
|
105
120
|
#
|
106
121
|
|
107
|
-
def
|
122
|
+
def _load_json_bytes(self, b: ta.Optional[bytes]) -> ta.Optional[ta.Any]:
|
123
|
+
if not b:
|
124
|
+
return None
|
125
|
+
return json.loads(b.decode('utf-8-sig'))
|
126
|
+
|
127
|
+
##
|
128
|
+
# requests
|
129
|
+
|
130
|
+
def _build_request_headers(
|
108
131
|
self,
|
109
132
|
headers: ta.Optional[ta.Mapping[str, str]] = None,
|
110
133
|
*,
|
134
|
+
no_auth: bool = False,
|
111
135
|
content_type: ta.Optional[str] = None,
|
112
136
|
json_content: bool = False,
|
113
137
|
) -> ta.Dict[str, str]:
|
114
|
-
dct = {
|
115
|
-
|
116
|
-
|
117
|
-
f'api-version={GithubCacheServiceV1.API_VERSION}',
|
118
|
-
]),
|
119
|
-
}
|
120
|
-
|
121
|
-
if (auth_token := self._auth_token):
|
138
|
+
dct = {}
|
139
|
+
|
140
|
+
if not no_auth and (auth_token := self._auth_token):
|
122
141
|
dct['Authorization'] = f'Bearer {auth_token}'
|
123
142
|
|
124
143
|
if content_type is None and json_content:
|
@@ -133,19 +152,13 @@ class GithubCacheServiceV1BaseClient(GithubCacheClient, abc.ABC):
|
|
133
152
|
|
134
153
|
#
|
135
154
|
|
136
|
-
def
|
137
|
-
if not b:
|
138
|
-
return None
|
139
|
-
return json.loads(b.decode('utf-8-sig'))
|
140
|
-
|
141
|
-
#
|
142
|
-
|
143
|
-
async def send_url_request(
|
155
|
+
async def _send_urllib_request(
|
144
156
|
self,
|
145
157
|
req: urllib.request.Request,
|
146
158
|
) -> ta.Tuple[http.client.HTTPResponse, ta.Optional[bytes]]:
|
147
159
|
def run_sync():
|
148
|
-
|
160
|
+
opener = urllib.request.build_opener(NonRaisingUrllibErrorProcessor)
|
161
|
+
with opener.open(req) as resp: # noqa
|
149
162
|
body = resp.read()
|
150
163
|
return (resp, body)
|
151
164
|
|
@@ -161,18 +174,32 @@ class GithubCacheServiceV1BaseClient(GithubCacheClient, abc.ABC):
|
|
161
174
|
def __str__(self) -> str:
|
162
175
|
return repr(self)
|
163
176
|
|
164
|
-
async def
|
177
|
+
async def _send_request(
|
165
178
|
self,
|
166
|
-
path: str,
|
167
179
|
*,
|
180
|
+
url: ta.Optional[str] = None,
|
181
|
+
path: ta.Optional[str] = None,
|
182
|
+
|
168
183
|
method: ta.Optional[str] = None,
|
184
|
+
|
169
185
|
headers: ta.Optional[ta.Mapping[str, str]] = None,
|
186
|
+
no_auth: bool = False,
|
170
187
|
content_type: ta.Optional[str] = None,
|
188
|
+
|
171
189
|
content: ta.Optional[bytes] = None,
|
172
190
|
json_content: ta.Optional[ta.Any] = None,
|
191
|
+
|
173
192
|
success_status_codes: ta.Optional[ta.Container[int]] = None,
|
193
|
+
|
194
|
+
retry_status_codes: ta.Optional[ta.Container[int]] = None,
|
195
|
+
num_retries: int = 0,
|
196
|
+
retry_sleep: ta.Optional[float] = None,
|
174
197
|
) -> ta.Optional[ta.Any]:
|
175
|
-
url
|
198
|
+
if url is not None and path is not None:
|
199
|
+
raise RuntimeError('Must not pass both url and path')
|
200
|
+
elif path is not None:
|
201
|
+
url = f'{self._service_url}/{path}'
|
202
|
+
url = check.non_empty_str(url)
|
176
203
|
|
177
204
|
if content is not None and json_content is not None:
|
178
205
|
raise RuntimeError('Must not pass both content and json_content')
|
@@ -185,33 +212,52 @@ class GithubCacheServiceV1BaseClient(GithubCacheClient, abc.ABC):
|
|
185
212
|
if method is None:
|
186
213
|
method = 'POST' if content is not None else 'GET'
|
187
214
|
|
215
|
+
headers = self._build_request_headers(
|
216
|
+
headers,
|
217
|
+
no_auth=no_auth,
|
218
|
+
content_type=content_type,
|
219
|
+
json_content=header_json_content,
|
220
|
+
)
|
221
|
+
|
188
222
|
#
|
189
223
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
headers,
|
195
|
-
|
196
|
-
|
197
|
-
),
|
198
|
-
data=content,
|
199
|
-
)
|
224
|
+
for n in itertools.count():
|
225
|
+
req = urllib.request.Request( # noqa
|
226
|
+
url,
|
227
|
+
method=method,
|
228
|
+
headers=headers,
|
229
|
+
data=content,
|
230
|
+
)
|
200
231
|
|
201
|
-
|
232
|
+
resp, body = await self._send_urllib_request(req)
|
202
233
|
|
203
|
-
|
234
|
+
#
|
204
235
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
236
|
+
if success_status_codes is not None:
|
237
|
+
is_success = resp.status in success_status_codes
|
238
|
+
else:
|
239
|
+
is_success = (200 <= resp.status < 300)
|
240
|
+
if is_success:
|
241
|
+
return self._load_json_bytes(body)
|
211
242
|
|
212
|
-
|
243
|
+
#
|
213
244
|
|
214
|
-
|
245
|
+
log.debug(f'Request to url {url} got unsuccessful status code {resp.status}') # noqa
|
246
|
+
|
247
|
+
if not (
|
248
|
+
retry_status_codes is not None and
|
249
|
+
resp.status in retry_status_codes and
|
250
|
+
n < num_retries
|
251
|
+
):
|
252
|
+
raise self.ServiceRequestError(resp.status, body)
|
253
|
+
|
254
|
+
if retry_sleep is not None:
|
255
|
+
await asyncio.sleep(retry_sleep)
|
256
|
+
|
257
|
+
raise RuntimeError('Unreachable')
|
258
|
+
|
259
|
+
##
|
260
|
+
# keys
|
215
261
|
|
216
262
|
KEY_PART_SEPARATOR = '---'
|
217
263
|
|
@@ -222,73 +268,8 @@ class GithubCacheServiceV1BaseClient(GithubCacheClient, abc.ABC):
|
|
222
268
|
('' if partial_suffix else self._key_suffix),
|
223
269
|
])
|
224
270
|
|
225
|
-
|
226
|
-
|
227
|
-
@dc.dataclass(frozen=True)
|
228
|
-
class Entry(GithubCacheClient.Entry):
|
229
|
-
artifact: GithubCacheServiceV1.ArtifactCacheEntry
|
230
|
-
|
231
|
-
def get_entry_url(self, entry: GithubCacheClient.Entry) -> ta.Optional[str]:
|
232
|
-
entry1 = check.isinstance(entry, self.Entry)
|
233
|
-
return entry1.artifact.archive_location
|
234
|
-
|
235
|
-
#
|
236
|
-
|
237
|
-
def build_get_entry_url_path(self, *keys: str) -> str:
|
238
|
-
qp = dict(
|
239
|
-
keys=','.join(urllib.parse.quote_plus(k) for k in keys),
|
240
|
-
version=str(self._cache_version),
|
241
|
-
)
|
242
|
-
|
243
|
-
return '?'.join([
|
244
|
-
'cache',
|
245
|
-
'&'.join([
|
246
|
-
f'{k}={v}'
|
247
|
-
for k, v in qp.items()
|
248
|
-
]),
|
249
|
-
])
|
250
|
-
|
251
|
-
GET_ENTRY_SUCCESS_STATUS_CODES = (200, 204)
|
252
|
-
|
253
|
-
|
254
|
-
##
|
255
|
-
|
256
|
-
|
257
|
-
class GithubCacheServiceV1Client(GithubCacheServiceV1BaseClient):
|
258
|
-
DEFAULT_CONCURRENCY = 4
|
259
|
-
|
260
|
-
DEFAULT_CHUNK_SIZE = 32 * 1024 * 1024
|
261
|
-
|
262
|
-
def __init__(
|
263
|
-
self,
|
264
|
-
*,
|
265
|
-
concurrency: int = DEFAULT_CONCURRENCY,
|
266
|
-
chunk_size: int = DEFAULT_CHUNK_SIZE,
|
267
|
-
**kwargs: ta.Any,
|
268
|
-
) -> None:
|
269
|
-
super().__init__(**kwargs)
|
270
|
-
|
271
|
-
check.arg(concurrency > 0)
|
272
|
-
self._concurrency = concurrency
|
273
|
-
|
274
|
-
check.arg(chunk_size > 0)
|
275
|
-
self._chunk_size = chunk_size
|
276
|
-
|
277
|
-
#
|
278
|
-
|
279
|
-
async def get_entry(self, key: str) -> ta.Optional[GithubCacheServiceV1BaseClient.Entry]:
|
280
|
-
obj = await self.send_service_request(
|
281
|
-
self.build_get_entry_url_path(self.fix_key(key, partial_suffix=True)),
|
282
|
-
)
|
283
|
-
if obj is None:
|
284
|
-
return None
|
285
|
-
|
286
|
-
return self.Entry(GithubCacheServiceV1.dataclass_from_json(
|
287
|
-
GithubCacheServiceV1.ArtifactCacheEntry,
|
288
|
-
obj,
|
289
|
-
))
|
290
|
-
|
291
|
-
#
|
271
|
+
##
|
272
|
+
# downloading
|
292
273
|
|
293
274
|
@dc.dataclass(frozen=True)
|
294
275
|
class _DownloadChunk:
|
@@ -306,7 +287,7 @@ class GithubCacheServiceV1Client(GithubCacheServiceV1BaseClient):
|
|
306
287
|
},
|
307
288
|
)
|
308
289
|
|
309
|
-
_, buf_ = await self.
|
290
|
+
_, buf_ = await self._send_urllib_request(req)
|
310
291
|
|
311
292
|
buf = check.not_none(buf_)
|
312
293
|
check.equal(len(buf), chunk.size)
|
@@ -349,7 +330,7 @@ class GithubCacheServiceV1Client(GithubCacheServiceV1BaseClient):
|
|
349
330
|
#
|
350
331
|
# status_code = check.isinstance(curl_res['response_code'], int)
|
351
332
|
#
|
352
|
-
# if not (200 <= status_code
|
333
|
+
# if not (200 <= status_code < 300):
|
353
334
|
# raise RuntimeError(f'Curl chunk download {chunk} failed: {curl_res}')
|
354
335
|
|
355
336
|
async def _download_file_chunk(self, chunk: _DownloadChunk) -> None:
|
@@ -361,11 +342,17 @@ class GithubCacheServiceV1Client(GithubCacheServiceV1BaseClient):
|
|
361
342
|
):
|
362
343
|
await self._download_file_chunk_urllib(chunk)
|
363
344
|
|
364
|
-
async def
|
365
|
-
|
366
|
-
|
345
|
+
async def _download_file_chunks(
|
346
|
+
self,
|
347
|
+
*,
|
348
|
+
key: str,
|
349
|
+
url: str,
|
350
|
+
out_file: str,
|
351
|
+
) -> None:
|
352
|
+
check.non_empty_str(key)
|
353
|
+
check.non_empty_str(url)
|
367
354
|
|
368
|
-
head_resp, _ = await self.
|
355
|
+
head_resp, _ = await self._send_urllib_request(urllib.request.Request( # noqa
|
369
356
|
url,
|
370
357
|
method='HEAD',
|
371
358
|
))
|
@@ -394,74 +381,68 @@ class GithubCacheServiceV1Client(GithubCacheServiceV1BaseClient):
|
|
394
381
|
|
395
382
|
await asyncio_wait_concurrent(download_tasks, self._concurrency)
|
396
383
|
|
397
|
-
|
398
|
-
|
399
|
-
with log_timing_context(
|
400
|
-
'Downloading github cache '
|
401
|
-
f'key {entry1.artifact.cache_key} '
|
402
|
-
f'version {entry1.artifact.cache_version} '
|
403
|
-
f'to {out_file}',
|
404
|
-
):
|
405
|
-
await self._download_file(entry1, out_file)
|
384
|
+
##
|
385
|
+
# uploading
|
406
386
|
|
407
|
-
|
387
|
+
@dc.dataclass(frozen=True)
|
388
|
+
class _UploadChunk:
|
389
|
+
url: str
|
390
|
+
key: str
|
391
|
+
in_file: str
|
392
|
+
offset: int
|
393
|
+
size: int
|
408
394
|
|
409
|
-
|
410
|
-
|
411
|
-
key: str,
|
412
|
-
cache_id: int,
|
413
|
-
in_file: str,
|
414
|
-
offset: int,
|
415
|
-
size: int,
|
416
|
-
) -> None:
|
417
|
-
with log_timing_context(
|
418
|
-
f'Uploading github cache {key} '
|
419
|
-
f'file {in_file} '
|
420
|
-
f'chunk {offset} - {offset + size}',
|
421
|
-
):
|
422
|
-
with open(in_file, 'rb') as f: # noqa
|
423
|
-
f.seek(offset)
|
424
|
-
buf = f.read(size)
|
425
|
-
|
426
|
-
check.equal(len(buf), size)
|
427
|
-
|
428
|
-
await self.send_service_request(
|
429
|
-
f'caches/{cache_id}',
|
430
|
-
method='PATCH',
|
431
|
-
content_type='application/octet-stream',
|
432
|
-
headers={
|
433
|
-
'Content-Range': f'bytes {offset}-{offset + size - 1}/*',
|
434
|
-
},
|
435
|
-
content=buf,
|
436
|
-
success_status_codes=[204],
|
437
|
-
)
|
395
|
+
UPLOAD_CHUNK_NUM_RETRIES = 10
|
396
|
+
UPLOAD_CHUNK_RETRY_SLEEP = .5
|
438
397
|
|
439
|
-
async def
|
440
|
-
|
398
|
+
async def _upload_file_chunk_(self, chunk: _UploadChunk) -> None:
|
399
|
+
with open(chunk.in_file, 'rb') as f: # noqa
|
400
|
+
f.seek(chunk.offset)
|
401
|
+
buf = f.read(chunk.size)
|
441
402
|
|
442
|
-
check.
|
403
|
+
check.equal(len(buf), chunk.size)
|
443
404
|
|
444
|
-
|
405
|
+
await self._send_request(
|
406
|
+
url=chunk.url,
|
445
407
|
|
446
|
-
|
408
|
+
method='PATCH',
|
447
409
|
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
success_status_codes=[
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
410
|
+
headers={
|
411
|
+
'Content-Range': f'bytes {chunk.offset}-{chunk.offset + chunk.size - 1}/*',
|
412
|
+
},
|
413
|
+
no_auth=True,
|
414
|
+
content_type='application/octet-stream',
|
415
|
+
|
416
|
+
content=buf,
|
417
|
+
|
418
|
+
success_status_codes=[204],
|
419
|
+
|
420
|
+
# retry_status_codes=[405],
|
421
|
+
num_retries=self.UPLOAD_CHUNK_NUM_RETRIES,
|
422
|
+
retry_sleep=self.UPLOAD_CHUNK_RETRY_SLEEP,
|
461
423
|
)
|
462
|
-
cache_id = check.isinstance(reserve_resp.cache_id, int)
|
463
424
|
|
464
|
-
|
425
|
+
async def _upload_file_chunk(self, chunk: _UploadChunk) -> None:
|
426
|
+
with log_timing_context(
|
427
|
+
f'Uploading github cache {chunk.key} '
|
428
|
+
f'file {chunk.in_file} '
|
429
|
+
f'chunk {chunk.offset} - {chunk.offset + chunk.size}',
|
430
|
+
):
|
431
|
+
await self._upload_file_chunk_(chunk)
|
432
|
+
|
433
|
+
async def _upload_file_chunks(
|
434
|
+
self,
|
435
|
+
*,
|
436
|
+
in_file: str,
|
437
|
+
url: str,
|
438
|
+
key: str,
|
439
|
+
|
440
|
+
file_size: ta.Optional[int] = None,
|
441
|
+
) -> None:
|
442
|
+
check.state(os.path.isfile(in_file))
|
443
|
+
|
444
|
+
if file_size is None:
|
445
|
+
file_size = os.stat(in_file).st_size
|
465
446
|
|
466
447
|
#
|
467
448
|
|
@@ -470,30 +451,12 @@ class GithubCacheServiceV1Client(GithubCacheServiceV1BaseClient):
|
|
470
451
|
for i in range((file_size // chunk_size) + (1 if file_size % chunk_size else 0)):
|
471
452
|
offset = i * chunk_size
|
472
453
|
size = min(chunk_size, file_size - offset)
|
473
|
-
upload_tasks.append(self._upload_file_chunk(
|
474
|
-
|
475
|
-
|
476
|
-
in_file,
|
477
|
-
offset,
|
478
|
-
size,
|
479
|
-
))
|
454
|
+
upload_tasks.append(self._upload_file_chunk(self._UploadChunk(
|
455
|
+
url=url,
|
456
|
+
key=key,
|
457
|
+
in_file=in_file,
|
458
|
+
offset=offset,
|
459
|
+
size=size,
|
460
|
+
)))
|
480
461
|
|
481
462
|
await asyncio_wait_concurrent(upload_tasks, self._concurrency)
|
482
|
-
|
483
|
-
#
|
484
|
-
|
485
|
-
commit_req = GithubCacheServiceV1.CommitCacheRequest(
|
486
|
-
size=file_size,
|
487
|
-
)
|
488
|
-
await self.send_service_request(
|
489
|
-
f'caches/{cache_id}',
|
490
|
-
json_content=GithubCacheServiceV1.dataclass_to_json(commit_req),
|
491
|
-
success_status_codes=[204],
|
492
|
-
)
|
493
|
-
|
494
|
-
async def upload_file(self, key: str, in_file: str) -> None:
|
495
|
-
with log_timing_context(
|
496
|
-
f'Uploading github cache file {os.path.basename(in_file)} '
|
497
|
-
f'key {key}',
|
498
|
-
):
|
499
|
-
await self._upload_file(key, in_file)
|
@@ -49,6 +49,11 @@ T = ta.TypeVar('T')
|
|
49
49
|
|
50
50
|
|
51
51
|
class GithubCacheServiceV1:
|
52
|
+
def __new__(cls, *args, **kwargs): # noqa
|
53
|
+
raise TypeError
|
54
|
+
|
55
|
+
#
|
56
|
+
|
52
57
|
API_VERSION = '6.0-preview.1'
|
53
58
|
|
54
59
|
@classmethod
|
@@ -117,90 +122,3 @@ class GithubCacheServiceV1:
|
|
117
122
|
compression_method: ta.Optional[str] # CompressionMethod
|
118
123
|
enable_cross_os_archive: ta.Optional[bool]
|
119
124
|
cache_size: ta.Optional[int]
|
120
|
-
|
121
|
-
|
122
|
-
class GithubCacheServiceV2:
|
123
|
-
SERVICE_NAME = 'github.actions.results.api.v1.CacheService'
|
124
|
-
|
125
|
-
@dc.dataclass(frozen=True)
|
126
|
-
class Method:
|
127
|
-
name: str
|
128
|
-
request: type
|
129
|
-
response: type
|
130
|
-
|
131
|
-
#
|
132
|
-
|
133
|
-
class CacheScopePermission:
|
134
|
-
READ = 1
|
135
|
-
WRITE = 2
|
136
|
-
ALL = READ | WRITE
|
137
|
-
|
138
|
-
@dc.dataclass(frozen=True)
|
139
|
-
class CacheScope:
|
140
|
-
scope: str
|
141
|
-
permission: int # CacheScopePermission
|
142
|
-
|
143
|
-
@dc.dataclass(frozen=True)
|
144
|
-
class CacheMetadata:
|
145
|
-
repository_id: int
|
146
|
-
scope: ta.Sequence['GithubCacheServiceV2.CacheScope']
|
147
|
-
|
148
|
-
#
|
149
|
-
|
150
|
-
@dc.dataclass(frozen=True)
|
151
|
-
class CreateCacheEntryRequest:
|
152
|
-
key: str
|
153
|
-
version: str
|
154
|
-
metadata: ta.Optional['GithubCacheServiceV2.CacheMetadata'] = None
|
155
|
-
|
156
|
-
@dc.dataclass(frozen=True)
|
157
|
-
class CreateCacheEntryResponse:
|
158
|
-
ok: bool
|
159
|
-
signed_upload_url: str
|
160
|
-
|
161
|
-
CREATE_CACHE_ENTRY_METHOD = Method(
|
162
|
-
'CreateCacheEntry',
|
163
|
-
CreateCacheEntryRequest,
|
164
|
-
CreateCacheEntryResponse,
|
165
|
-
)
|
166
|
-
|
167
|
-
#
|
168
|
-
|
169
|
-
@dc.dataclass(frozen=True)
|
170
|
-
class FinalizeCacheEntryUploadRequest:
|
171
|
-
key: str
|
172
|
-
size_bytes: int
|
173
|
-
version: str
|
174
|
-
metadata: ta.Optional['GithubCacheServiceV2.CacheMetadata'] = None
|
175
|
-
|
176
|
-
@dc.dataclass(frozen=True)
|
177
|
-
class FinalizeCacheEntryUploadResponse:
|
178
|
-
ok: bool
|
179
|
-
entry_id: str
|
180
|
-
|
181
|
-
FINALIZE_CACHE_ENTRY_METHOD = Method(
|
182
|
-
'FinalizeCacheEntryUpload',
|
183
|
-
FinalizeCacheEntryUploadRequest,
|
184
|
-
FinalizeCacheEntryUploadResponse,
|
185
|
-
)
|
186
|
-
|
187
|
-
#
|
188
|
-
|
189
|
-
@dc.dataclass(frozen=True)
|
190
|
-
class GetCacheEntryDownloadUrlRequest:
|
191
|
-
key: str
|
192
|
-
restore_keys: ta.Sequence[str]
|
193
|
-
version: str
|
194
|
-
metadata: ta.Optional['GithubCacheServiceV2.CacheMetadata'] = None
|
195
|
-
|
196
|
-
@dc.dataclass(frozen=True)
|
197
|
-
class GetCacheEntryDownloadUrlResponse:
|
198
|
-
ok: bool
|
199
|
-
signed_download_url: str
|
200
|
-
matched_key: str
|
201
|
-
|
202
|
-
GET_CACHE_ENTRY_DOWNLOAD_URL_METHOD = Method(
|
203
|
-
'GetCacheEntryDownloadURL',
|
204
|
-
GetCacheEntryDownloadUrlRequest,
|
205
|
-
GetCacheEntryDownloadUrlResponse,
|
206
|
-
)
|