omdev 0.0.0.dev181__tar.gz → 0.0.0.dev182__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.dev181/omdev.egg-info → omdev-0.0.0.dev182}/PKG-INFO +2 -2
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/interp/inject.py +1 -1
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/interp/pyenv/inject.py +1 -1
- omdev-0.0.0.dev181/omdev/interp/pyenv/pyenv.py → omdev-0.0.0.dev182/omdev/interp/pyenv/install.py +1 -219
- omdev-0.0.0.dev182/omdev/interp/pyenv/provider.py +144 -0
- omdev-0.0.0.dev182/omdev/interp/pyenv/pyenv.py +86 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/scripts/interp.py +104 -102
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/scripts/pyproject.py +214 -212
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182/omdev.egg-info}/PKG-INFO +2 -2
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev.egg-info/SOURCES.txt +2 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev.egg-info/requires.txt +1 -1
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/pyproject.toml +2 -2
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/LICENSE +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/MANIFEST.in +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/README.rst +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/.manifests.json +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/__about__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/__init__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/amalg/__init__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/amalg/__main__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/amalg/gen.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/amalg/imports.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/amalg/main.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/amalg/manifests.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/amalg/resources.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/amalg/srcfiles.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/amalg/strip.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/amalg/types.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/amalg/typing.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/antlr/__init__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/antlr/consts.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/antlr/gen.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/bracepy.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cache/__init__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cache/compute/__init__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cache/compute/cache.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cache/compute/contexts.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cache/compute/currents.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cache/compute/fns.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cache/compute/resolvers.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cache/compute/storage.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cache/compute/types.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cache/data/__init__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cache/data/actions.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cache/data/cache.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cache/data/consts.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cache/data/defaults.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cache/data/manifests.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cache/data/specs.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cexts/__init__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cexts/_boilerplate.cc +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cexts/_distutils/LICENSE +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cexts/_distutils/__init__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cexts/_distutils/build_ext.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cexts/_distutils/compilers/__init__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cexts/_distutils/compilers/ccompiler.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cexts/_distutils/compilers/options.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cexts/_distutils/compilers/unixccompiler.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cexts/_distutils/dir_util.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cexts/_distutils/errors.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cexts/_distutils/extension.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cexts/_distutils/file_util.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cexts/_distutils/modified.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cexts/_distutils/spawn.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cexts/_distutils/sysconfig.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cexts/_distutils/util.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cexts/_distutils/version.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cexts/build.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cexts/cmake.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cexts/importhook.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cexts/magic.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cexts/scan.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/classdot.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cli/__init__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cli/__main__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cli/_pathhack.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cli/clicli.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cli/install.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cli/main.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cli/managers.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cli/types.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/clipboard/__init__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/clipboard/clipboard.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/clipboard/darwin_cf.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/clipboard/linux_x11.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/cmake.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/findimports.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/git/__init__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/git/revisions.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/git/status.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/git/subtrees.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/imgur.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/interp/__init__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/interp/__main__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/interp/cli.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/interp/default.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/interp/inspect.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/interp/providers/__init__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/interp/providers/base.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/interp/providers/inject.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/interp/providers/running.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/interp/providers/standalone.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/interp/providers/system.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/interp/pyenv/__init__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/interp/resolvers.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/interp/types.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/interp/uv/__init__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/interp/uv/inject.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/interp/uv/uv.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/interp/venvs.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/magic/__init__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/magic/__main__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/magic/cli.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/magic/find.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/magic/magic.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/magic/prepare.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/magic/styles.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/manifests/__init__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/manifests/__main__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/manifests/build.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/manifests/main.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/mypy/__init__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/mypy/debug.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/packaging/__init__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/packaging/marshal.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/packaging/names.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/packaging/requires.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/packaging/specifiers.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/packaging/versions.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/pip.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/precheck/__init__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/precheck/__main__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/precheck/base.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/precheck/git.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/precheck/lite.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/precheck/main.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/precheck/manifests.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/precheck/scripts.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/ptk/__init__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/ptk/apps/__init__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/ptk/apps/ncdu.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/pycharm/__init__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/pycharm/__main__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/pycharm/cli.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/pyproject/__init__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/pyproject/__main__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/pyproject/cexts.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/pyproject/cli.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/pyproject/configs.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/pyproject/inject.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/pyproject/pkg.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/pyproject/reqs.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/pyproject/venvs.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/revisions.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/scripts/__init__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/scripts/bumpversion.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/scripts/execrss.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/scripts/exectime.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/scripts/importtrace.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/scripts/slowcat.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/scripts/tmpexec.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/secrets.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/tokens.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/toml/__init__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/toml/parser.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/toml/writer.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/tools/__init__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/tools/cloc.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/tools/doc.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/tools/docker.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/tools/git.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/tools/importscan.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/tools/json/__init__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/tools/json/__main__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/tools/json/cli.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/tools/json/formats.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/tools/json/io.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/tools/json/parsing.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/tools/json/processing.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/tools/json/rendering.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/tools/mkrelimp.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/tools/notebook.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/tools/pawk/__init__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/tools/pawk/__main__.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/tools/pawk/pawk.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/tools/pip.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/tools/prof.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/tools/qr.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/tools/sqlrepl.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev/wheelfile.py +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev.egg-info/dependency_links.txt +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev.egg-info/entry_points.txt +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/omdev.egg-info/top_level.txt +0 -0
- {omdev-0.0.0.dev181 → omdev-0.0.0.dev182}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: omdev
|
|
3
|
-
Version: 0.0.0.
|
|
3
|
+
Version: 0.0.0.dev182
|
|
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.dev182
|
|
16
16
|
Provides-Extra: all
|
|
17
17
|
Requires-Dist: black~=24.10; extra == "all"
|
|
18
18
|
Requires-Dist: pycparser~=2.22; extra == "all"
|
|
@@ -11,7 +11,7 @@ from .providers.inject import bind_interp_providers
|
|
|
11
11
|
from .providers.running import RunningInterpProvider
|
|
12
12
|
from .providers.system import SystemInterpProvider
|
|
13
13
|
from .pyenv.inject import bind_interp_pyenv
|
|
14
|
-
from .pyenv.
|
|
14
|
+
from .pyenv.provider import PyenvInterpProvider
|
|
15
15
|
from .resolvers import InterpResolver
|
|
16
16
|
from .resolvers import InterpResolverProviders
|
|
17
17
|
from .uv.inject import bind_interp_uv
|
|
@@ -6,8 +6,8 @@ from omlish.lite.inject import InjectorBindings
|
|
|
6
6
|
from omlish.lite.inject import inj
|
|
7
7
|
|
|
8
8
|
from ..providers.base import InterpProvider
|
|
9
|
+
from .provider import PyenvInterpProvider
|
|
9
10
|
from .pyenv import Pyenv
|
|
10
|
-
from .pyenv import PyenvInterpProvider
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
def bind_interp_pyenv() -> InjectorBindings:
|
omdev-0.0.0.dev181/omdev/interp/pyenv/pyenv.py → omdev-0.0.0.dev182/omdev/interp/pyenv/install.py
RENAMED
|
@@ -1,19 +1,7 @@
|
|
|
1
1
|
# ruff: noqa: UP006 UP007
|
|
2
|
-
"""
|
|
3
|
-
TODO:
|
|
4
|
-
- custom tags
|
|
5
|
-
- 'aliases'
|
|
6
|
-
- https://github.com/pyenv/pyenv/pull/2966
|
|
7
|
-
- https://github.com/pyenv/pyenv/issues/218 (lol)
|
|
8
|
-
- probably need custom (temp?) definition file
|
|
9
|
-
- *or* python-build directly just into the versions dir?
|
|
10
|
-
- optionally install / upgrade pyenv itself
|
|
11
|
-
- new vers dont need these custom mac opts, only run on old vers
|
|
12
|
-
"""
|
|
13
2
|
import abc
|
|
14
3
|
import dataclasses as dc
|
|
15
4
|
import itertools
|
|
16
|
-
import logging
|
|
17
5
|
import os.path
|
|
18
6
|
import shutil
|
|
19
7
|
import sys
|
|
@@ -24,84 +12,8 @@ from omlish.lite.cached import async_cached_nullary
|
|
|
24
12
|
from omlish.lite.cached import cached_nullary
|
|
25
13
|
from omlish.lite.check import check
|
|
26
14
|
|
|
27
|
-
from ...packaging.versions import InvalidVersion
|
|
28
|
-
from ...packaging.versions import Version
|
|
29
|
-
from ..inspect import InterpInspector
|
|
30
|
-
from ..providers.base import InterpProvider
|
|
31
|
-
from ..types import Interp
|
|
32
15
|
from ..types import InterpOpts
|
|
33
|
-
from
|
|
34
|
-
from ..types import InterpVersion
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
##
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
class Pyenv:
|
|
41
|
-
def __init__(
|
|
42
|
-
self,
|
|
43
|
-
*,
|
|
44
|
-
root: ta.Optional[str] = None,
|
|
45
|
-
) -> None:
|
|
46
|
-
if root is not None and not (isinstance(root, str) and root):
|
|
47
|
-
raise ValueError(f'pyenv_root: {root!r}')
|
|
48
|
-
|
|
49
|
-
super().__init__()
|
|
50
|
-
|
|
51
|
-
self._root_kw = root
|
|
52
|
-
|
|
53
|
-
@async_cached_nullary
|
|
54
|
-
async def root(self) -> ta.Optional[str]:
|
|
55
|
-
if self._root_kw is not None:
|
|
56
|
-
return self._root_kw
|
|
57
|
-
|
|
58
|
-
if shutil.which('pyenv'):
|
|
59
|
-
return await asyncio_subprocesses.check_output_str('pyenv', 'root')
|
|
60
|
-
|
|
61
|
-
d = os.path.expanduser('~/.pyenv')
|
|
62
|
-
if os.path.isdir(d) and os.path.isfile(os.path.join(d, 'bin', 'pyenv')):
|
|
63
|
-
return d
|
|
64
|
-
|
|
65
|
-
return None
|
|
66
|
-
|
|
67
|
-
@async_cached_nullary
|
|
68
|
-
async def exe(self) -> str:
|
|
69
|
-
return os.path.join(check.not_none(await self.root()), 'bin', 'pyenv')
|
|
70
|
-
|
|
71
|
-
async def version_exes(self) -> ta.List[ta.Tuple[str, str]]:
|
|
72
|
-
if (root := await self.root()) is None:
|
|
73
|
-
return []
|
|
74
|
-
ret = []
|
|
75
|
-
vp = os.path.join(root, 'versions')
|
|
76
|
-
if os.path.isdir(vp):
|
|
77
|
-
for dn in os.listdir(vp):
|
|
78
|
-
ep = os.path.join(vp, dn, 'bin', 'python')
|
|
79
|
-
if not os.path.isfile(ep):
|
|
80
|
-
continue
|
|
81
|
-
ret.append((dn, ep))
|
|
82
|
-
return ret
|
|
83
|
-
|
|
84
|
-
async def installable_versions(self) -> ta.List[str]:
|
|
85
|
-
if await self.root() is None:
|
|
86
|
-
return []
|
|
87
|
-
ret = []
|
|
88
|
-
s = await asyncio_subprocesses.check_output_str(await self.exe(), 'install', '--list')
|
|
89
|
-
for l in s.splitlines():
|
|
90
|
-
if not l.startswith(' '):
|
|
91
|
-
continue
|
|
92
|
-
l = l.strip()
|
|
93
|
-
if not l:
|
|
94
|
-
continue
|
|
95
|
-
ret.append(l)
|
|
96
|
-
return ret
|
|
97
|
-
|
|
98
|
-
async def update(self) -> bool:
|
|
99
|
-
if (root := await self.root()) is None:
|
|
100
|
-
return False
|
|
101
|
-
if not os.path.isdir(os.path.join(root, '.git')):
|
|
102
|
-
return False
|
|
103
|
-
await asyncio_subprocesses.check_call('git', 'pull', cwd=root)
|
|
104
|
-
return True
|
|
16
|
+
from .pyenv import Pyenv
|
|
105
17
|
|
|
106
18
|
|
|
107
19
|
##
|
|
@@ -337,133 +249,3 @@ class PyenvVersionInstaller:
|
|
|
337
249
|
if not os.path.isfile(exe):
|
|
338
250
|
raise RuntimeError(f'Interpreter not found: {exe}')
|
|
339
251
|
return exe
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
##
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
class PyenvInterpProvider(InterpProvider):
|
|
346
|
-
@dc.dataclass(frozen=True)
|
|
347
|
-
class Options:
|
|
348
|
-
inspect: bool = False
|
|
349
|
-
|
|
350
|
-
try_update: bool = False
|
|
351
|
-
|
|
352
|
-
def __init__(
|
|
353
|
-
self,
|
|
354
|
-
options: Options = Options(),
|
|
355
|
-
*,
|
|
356
|
-
pyenv: Pyenv,
|
|
357
|
-
inspector: InterpInspector,
|
|
358
|
-
log: ta.Optional[logging.Logger] = None,
|
|
359
|
-
) -> None:
|
|
360
|
-
super().__init__()
|
|
361
|
-
|
|
362
|
-
self._options = options
|
|
363
|
-
|
|
364
|
-
self._pyenv = pyenv
|
|
365
|
-
self._inspector = inspector
|
|
366
|
-
self._log = log
|
|
367
|
-
|
|
368
|
-
#
|
|
369
|
-
|
|
370
|
-
@staticmethod
|
|
371
|
-
def guess_version(s: str) -> ta.Optional[InterpVersion]:
|
|
372
|
-
def strip_sfx(s: str, sfx: str) -> ta.Tuple[str, bool]:
|
|
373
|
-
if s.endswith(sfx):
|
|
374
|
-
return s[:-len(sfx)], True
|
|
375
|
-
return s, False
|
|
376
|
-
ok = {}
|
|
377
|
-
s, ok['debug'] = strip_sfx(s, '-debug')
|
|
378
|
-
s, ok['threaded'] = strip_sfx(s, 't')
|
|
379
|
-
try:
|
|
380
|
-
v = Version(s)
|
|
381
|
-
except InvalidVersion:
|
|
382
|
-
return None
|
|
383
|
-
return InterpVersion(v, InterpOpts(**ok))
|
|
384
|
-
|
|
385
|
-
class Installed(ta.NamedTuple):
|
|
386
|
-
name: str
|
|
387
|
-
exe: str
|
|
388
|
-
version: InterpVersion
|
|
389
|
-
|
|
390
|
-
async def _make_installed(self, vn: str, ep: str) -> ta.Optional[Installed]:
|
|
391
|
-
iv: ta.Optional[InterpVersion]
|
|
392
|
-
if self._options.inspect:
|
|
393
|
-
try:
|
|
394
|
-
iv = check.not_none(await self._inspector.inspect(ep)).iv
|
|
395
|
-
except Exception as e: # noqa
|
|
396
|
-
return None
|
|
397
|
-
else:
|
|
398
|
-
iv = self.guess_version(vn)
|
|
399
|
-
if iv is None:
|
|
400
|
-
return None
|
|
401
|
-
return PyenvInterpProvider.Installed(
|
|
402
|
-
name=vn,
|
|
403
|
-
exe=ep,
|
|
404
|
-
version=iv,
|
|
405
|
-
)
|
|
406
|
-
|
|
407
|
-
async def installed(self) -> ta.Sequence[Installed]:
|
|
408
|
-
ret: ta.List[PyenvInterpProvider.Installed] = []
|
|
409
|
-
for vn, ep in await self._pyenv.version_exes():
|
|
410
|
-
if (i := await self._make_installed(vn, ep)) is None:
|
|
411
|
-
if self._log is not None:
|
|
412
|
-
self._log.debug('Invalid pyenv version: %s', vn)
|
|
413
|
-
continue
|
|
414
|
-
ret.append(i)
|
|
415
|
-
return ret
|
|
416
|
-
|
|
417
|
-
#
|
|
418
|
-
|
|
419
|
-
async def get_installed_versions(self, spec: InterpSpecifier) -> ta.Sequence[InterpVersion]:
|
|
420
|
-
return [i.version for i in await self.installed()]
|
|
421
|
-
|
|
422
|
-
async def get_installed_version(self, version: InterpVersion) -> Interp:
|
|
423
|
-
for i in await self.installed():
|
|
424
|
-
if i.version == version:
|
|
425
|
-
return Interp(
|
|
426
|
-
exe=i.exe,
|
|
427
|
-
version=i.version,
|
|
428
|
-
)
|
|
429
|
-
raise KeyError(version)
|
|
430
|
-
|
|
431
|
-
#
|
|
432
|
-
|
|
433
|
-
async def _get_installable_versions(self, spec: InterpSpecifier) -> ta.Sequence[InterpVersion]:
|
|
434
|
-
lst = []
|
|
435
|
-
|
|
436
|
-
for vs in await self._pyenv.installable_versions():
|
|
437
|
-
if (iv := self.guess_version(vs)) is None:
|
|
438
|
-
continue
|
|
439
|
-
if iv.opts.debug:
|
|
440
|
-
raise Exception('Pyenv installable versions not expected to have debug suffix')
|
|
441
|
-
for d in [False, True]:
|
|
442
|
-
lst.append(dc.replace(iv, opts=dc.replace(iv.opts, debug=d)))
|
|
443
|
-
|
|
444
|
-
return lst
|
|
445
|
-
|
|
446
|
-
async def get_installable_versions(self, spec: InterpSpecifier) -> ta.Sequence[InterpVersion]:
|
|
447
|
-
lst = await self._get_installable_versions(spec)
|
|
448
|
-
|
|
449
|
-
if self._options.try_update and not any(v in spec for v in lst):
|
|
450
|
-
if self._pyenv.update():
|
|
451
|
-
lst = await self._get_installable_versions(spec)
|
|
452
|
-
|
|
453
|
-
return lst
|
|
454
|
-
|
|
455
|
-
async def install_version(self, version: InterpVersion) -> Interp:
|
|
456
|
-
inst_version = str(version.version)
|
|
457
|
-
inst_opts = version.opts
|
|
458
|
-
if inst_opts.threaded:
|
|
459
|
-
inst_version += 't'
|
|
460
|
-
inst_opts = dc.replace(inst_opts, threaded=False)
|
|
461
|
-
|
|
462
|
-
installer = PyenvVersionInstaller(
|
|
463
|
-
inst_version,
|
|
464
|
-
interp_opts=inst_opts,
|
|
465
|
-
pyenv=self._pyenv,
|
|
466
|
-
)
|
|
467
|
-
|
|
468
|
-
exe = await installer.install()
|
|
469
|
-
return Interp(exe, version)
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# ruff: noqa: UP006 UP007
|
|
2
|
+
import dataclasses as dc
|
|
3
|
+
import logging
|
|
4
|
+
import typing as ta
|
|
5
|
+
|
|
6
|
+
from omlish.lite.check import check
|
|
7
|
+
|
|
8
|
+
from ...packaging.versions import InvalidVersion
|
|
9
|
+
from ...packaging.versions import Version
|
|
10
|
+
from ..inspect import InterpInspector
|
|
11
|
+
from ..providers.base import InterpProvider
|
|
12
|
+
from ..types import Interp
|
|
13
|
+
from ..types import InterpOpts
|
|
14
|
+
from ..types import InterpSpecifier
|
|
15
|
+
from ..types import InterpVersion
|
|
16
|
+
from .install import PyenvVersionInstaller
|
|
17
|
+
from .pyenv import Pyenv
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class PyenvInterpProvider(InterpProvider):
|
|
21
|
+
@dc.dataclass(frozen=True)
|
|
22
|
+
class Options:
|
|
23
|
+
inspect: bool = False
|
|
24
|
+
|
|
25
|
+
try_update: bool = False
|
|
26
|
+
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
options: Options = Options(),
|
|
30
|
+
*,
|
|
31
|
+
pyenv: Pyenv,
|
|
32
|
+
inspector: InterpInspector,
|
|
33
|
+
log: ta.Optional[logging.Logger] = None,
|
|
34
|
+
) -> None:
|
|
35
|
+
super().__init__()
|
|
36
|
+
|
|
37
|
+
self._options = options
|
|
38
|
+
|
|
39
|
+
self._pyenv = pyenv
|
|
40
|
+
self._inspector = inspector
|
|
41
|
+
self._log = log
|
|
42
|
+
|
|
43
|
+
#
|
|
44
|
+
|
|
45
|
+
@staticmethod
|
|
46
|
+
def guess_version(s: str) -> ta.Optional[InterpVersion]:
|
|
47
|
+
def strip_sfx(s: str, sfx: str) -> ta.Tuple[str, bool]:
|
|
48
|
+
if s.endswith(sfx):
|
|
49
|
+
return s[:-len(sfx)], True
|
|
50
|
+
return s, False
|
|
51
|
+
ok = {}
|
|
52
|
+
s, ok['debug'] = strip_sfx(s, '-debug')
|
|
53
|
+
s, ok['threaded'] = strip_sfx(s, 't')
|
|
54
|
+
try:
|
|
55
|
+
v = Version(s)
|
|
56
|
+
except InvalidVersion:
|
|
57
|
+
return None
|
|
58
|
+
return InterpVersion(v, InterpOpts(**ok))
|
|
59
|
+
|
|
60
|
+
class Installed(ta.NamedTuple):
|
|
61
|
+
name: str
|
|
62
|
+
exe: str
|
|
63
|
+
version: InterpVersion
|
|
64
|
+
|
|
65
|
+
async def _make_installed(self, vn: str, ep: str) -> ta.Optional[Installed]:
|
|
66
|
+
iv: ta.Optional[InterpVersion]
|
|
67
|
+
if self._options.inspect:
|
|
68
|
+
try:
|
|
69
|
+
iv = check.not_none(await self._inspector.inspect(ep)).iv
|
|
70
|
+
except Exception as e: # noqa
|
|
71
|
+
return None
|
|
72
|
+
else:
|
|
73
|
+
iv = self.guess_version(vn)
|
|
74
|
+
if iv is None:
|
|
75
|
+
return None
|
|
76
|
+
return PyenvInterpProvider.Installed(
|
|
77
|
+
name=vn,
|
|
78
|
+
exe=ep,
|
|
79
|
+
version=iv,
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
async def installed(self) -> ta.Sequence[Installed]:
|
|
83
|
+
ret: ta.List[PyenvInterpProvider.Installed] = []
|
|
84
|
+
for vn, ep in await self._pyenv.version_exes():
|
|
85
|
+
if (i := await self._make_installed(vn, ep)) is None:
|
|
86
|
+
if self._log is not None:
|
|
87
|
+
self._log.debug('Invalid pyenv version: %s', vn)
|
|
88
|
+
continue
|
|
89
|
+
ret.append(i)
|
|
90
|
+
return ret
|
|
91
|
+
|
|
92
|
+
#
|
|
93
|
+
|
|
94
|
+
async def get_installed_versions(self, spec: InterpSpecifier) -> ta.Sequence[InterpVersion]:
|
|
95
|
+
return [i.version for i in await self.installed()]
|
|
96
|
+
|
|
97
|
+
async def get_installed_version(self, version: InterpVersion) -> Interp:
|
|
98
|
+
for i in await self.installed():
|
|
99
|
+
if i.version == version:
|
|
100
|
+
return Interp(
|
|
101
|
+
exe=i.exe,
|
|
102
|
+
version=i.version,
|
|
103
|
+
)
|
|
104
|
+
raise KeyError(version)
|
|
105
|
+
|
|
106
|
+
#
|
|
107
|
+
|
|
108
|
+
async def _get_installable_versions(self, spec: InterpSpecifier) -> ta.Sequence[InterpVersion]:
|
|
109
|
+
lst = []
|
|
110
|
+
|
|
111
|
+
for vs in await self._pyenv.installable_versions():
|
|
112
|
+
if (iv := self.guess_version(vs)) is None:
|
|
113
|
+
continue
|
|
114
|
+
if iv.opts.debug:
|
|
115
|
+
raise Exception('Pyenv installable versions not expected to have debug suffix')
|
|
116
|
+
for d in [False, True]:
|
|
117
|
+
lst.append(dc.replace(iv, opts=dc.replace(iv.opts, debug=d)))
|
|
118
|
+
|
|
119
|
+
return lst
|
|
120
|
+
|
|
121
|
+
async def get_installable_versions(self, spec: InterpSpecifier) -> ta.Sequence[InterpVersion]:
|
|
122
|
+
lst = await self._get_installable_versions(spec)
|
|
123
|
+
|
|
124
|
+
if self._options.try_update and not any(v in spec for v in lst):
|
|
125
|
+
if self._pyenv.update():
|
|
126
|
+
lst = await self._get_installable_versions(spec)
|
|
127
|
+
|
|
128
|
+
return lst
|
|
129
|
+
|
|
130
|
+
async def install_version(self, version: InterpVersion) -> Interp:
|
|
131
|
+
inst_version = str(version.version)
|
|
132
|
+
inst_opts = version.opts
|
|
133
|
+
if inst_opts.threaded:
|
|
134
|
+
inst_version += 't'
|
|
135
|
+
inst_opts = dc.replace(inst_opts, threaded=False)
|
|
136
|
+
|
|
137
|
+
installer = PyenvVersionInstaller(
|
|
138
|
+
inst_version,
|
|
139
|
+
interp_opts=inst_opts,
|
|
140
|
+
pyenv=self._pyenv,
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
exe = await installer.install()
|
|
144
|
+
return Interp(exe, version)
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# ruff: noqa: UP006 UP007
|
|
2
|
+
"""
|
|
3
|
+
TODO:
|
|
4
|
+
- custom tags
|
|
5
|
+
- 'aliases'
|
|
6
|
+
- https://github.com/pyenv/pyenv/pull/2966
|
|
7
|
+
- https://github.com/pyenv/pyenv/issues/218 (lol)
|
|
8
|
+
- probably need custom (temp?) definition file
|
|
9
|
+
- *or* python-build directly just into the versions dir?
|
|
10
|
+
- optionally install / upgrade pyenv itself
|
|
11
|
+
- new vers dont need these custom mac opts, only run on old vers
|
|
12
|
+
"""
|
|
13
|
+
import os.path
|
|
14
|
+
import shutil
|
|
15
|
+
import typing as ta
|
|
16
|
+
|
|
17
|
+
from omlish.asyncs.asyncio.subprocesses import asyncio_subprocesses
|
|
18
|
+
from omlish.lite.cached import async_cached_nullary
|
|
19
|
+
from omlish.lite.check import check
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class Pyenv:
|
|
23
|
+
def __init__(
|
|
24
|
+
self,
|
|
25
|
+
*,
|
|
26
|
+
root: ta.Optional[str] = None,
|
|
27
|
+
) -> None:
|
|
28
|
+
if root is not None and not (isinstance(root, str) and root):
|
|
29
|
+
raise ValueError(f'pyenv_root: {root!r}')
|
|
30
|
+
|
|
31
|
+
super().__init__()
|
|
32
|
+
|
|
33
|
+
self._root_kw = root
|
|
34
|
+
|
|
35
|
+
@async_cached_nullary
|
|
36
|
+
async def root(self) -> ta.Optional[str]:
|
|
37
|
+
if self._root_kw is not None:
|
|
38
|
+
return self._root_kw
|
|
39
|
+
|
|
40
|
+
if shutil.which('pyenv'):
|
|
41
|
+
return await asyncio_subprocesses.check_output_str('pyenv', 'root')
|
|
42
|
+
|
|
43
|
+
d = os.path.expanduser('~/.pyenv')
|
|
44
|
+
if os.path.isdir(d) and os.path.isfile(os.path.join(d, 'bin', 'pyenv')):
|
|
45
|
+
return d
|
|
46
|
+
|
|
47
|
+
return None
|
|
48
|
+
|
|
49
|
+
@async_cached_nullary
|
|
50
|
+
async def exe(self) -> str:
|
|
51
|
+
return os.path.join(check.not_none(await self.root()), 'bin', 'pyenv')
|
|
52
|
+
|
|
53
|
+
async def version_exes(self) -> ta.List[ta.Tuple[str, str]]:
|
|
54
|
+
if (root := await self.root()) is None:
|
|
55
|
+
return []
|
|
56
|
+
ret = []
|
|
57
|
+
vp = os.path.join(root, 'versions')
|
|
58
|
+
if os.path.isdir(vp):
|
|
59
|
+
for dn in os.listdir(vp):
|
|
60
|
+
ep = os.path.join(vp, dn, 'bin', 'python')
|
|
61
|
+
if not os.path.isfile(ep):
|
|
62
|
+
continue
|
|
63
|
+
ret.append((dn, ep))
|
|
64
|
+
return ret
|
|
65
|
+
|
|
66
|
+
async def installable_versions(self) -> ta.List[str]:
|
|
67
|
+
if await self.root() is None:
|
|
68
|
+
return []
|
|
69
|
+
ret = []
|
|
70
|
+
s = await asyncio_subprocesses.check_output_str(await self.exe(), 'install', '--list')
|
|
71
|
+
for l in s.splitlines():
|
|
72
|
+
if not l.startswith(' '):
|
|
73
|
+
continue
|
|
74
|
+
l = l.strip()
|
|
75
|
+
if not l:
|
|
76
|
+
continue
|
|
77
|
+
ret.append(l)
|
|
78
|
+
return ret
|
|
79
|
+
|
|
80
|
+
async def update(self) -> bool:
|
|
81
|
+
if (root := await self.root()) is None:
|
|
82
|
+
return False
|
|
83
|
+
if not os.path.isdir(os.path.join(root, '.git')):
|
|
84
|
+
return False
|
|
85
|
+
await asyncio_subprocesses.check_call('git', 'pull', cwd=root)
|
|
86
|
+
return True
|