omdev 0.0.51__tar.gz → 0.0.52__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.51/omdev.egg-info → omdev-0.0.52}/PKG-INFO +12 -12
- {omdev-0.0.51 → omdev-0.0.52}/omdev/.om-manifests.json +2 -2
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/resources/.python-versions.json +4 -4
- omdev-0.0.52/omdev/scripts/ghajunit.py +477 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/scripts/slowcat.py +3 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/scripts/tmpexec.py +3 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/README.md +11 -10
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/__init__.py +7 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/_dataclasses.py +78 -76
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/_devdocs/dev_01_parity_push.md +18 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/controls/textarea.py +24 -3
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/docs/positions.py +3 -2
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/events/types.py +16 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/runtime/asyncio.py +104 -18
- omdev-0.0.52/omdev/tui/minitui/runtime/jobcontrol.py +73 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/runtime/sync.py +97 -9
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/surfaces/alts.py +6 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/surfaces/base.py +16 -3
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/surfaces/inlines.py +30 -8
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/text/themes.py +1 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/tty/terminals.py +13 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/vim/_dataclasses.py +45 -20
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/vim/options.py +4 -1
- {omdev-0.0.51 → omdev-0.0.52/omdev.egg-info}/PKG-INFO +12 -12
- {omdev-0.0.51 → omdev-0.0.52}/omdev.egg-info/SOURCES.txt +2 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev.egg-info/requires.txt +11 -11
- {omdev-0.0.51 → omdev-0.0.52}/pyproject.toml +12 -12
- {omdev-0.0.51 → omdev-0.0.52}/LICENSE +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/MANIFEST.in +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/README.md +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/README.md +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/__about__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/amalg/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/amalg/__main__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/amalg/cli/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/amalg/cli/main.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/amalg/gen/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/amalg/gen/gen.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/amalg/gen/imports.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/amalg/gen/manifests.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/amalg/gen/resources.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/amalg/gen/srcfiles.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/amalg/gen/strip.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/amalg/gen/types.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/amalg/gen/typing.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/amalg/info.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/amalg/sources.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cache/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cache/compute/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cache/compute/cache.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cache/compute/contexts.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cache/compute/currents.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cache/compute/fns.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cache/compute/resolvers.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cache/compute/storage.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cache/compute/types.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cache/data/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cache/data/actions.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cache/data/cache.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cache/data/consts.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cache/data/defaults.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cache/data/manifests.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cache/data/specs.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/capi/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/capi/darwin/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/capi/darwin/aps.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/capi/darwin/ax.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/capi/darwin/cf.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/capi/darwin/cg.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/capi/linux/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/capi/linux/x11.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cc/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cc/__main__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cc/cdeps.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cc/cdeps.toml +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cc/cli.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cc/srclangs.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cexts/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cexts/_boilerplate.cc +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cexts/_distutils/LICENSE +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cexts/_distutils/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cexts/_distutils/build_ext.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cexts/_distutils/compilers/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cexts/_distutils/compilers/ccompiler.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cexts/_distutils/compilers/options.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cexts/_distutils/compilers/unixccompiler.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cexts/_distutils/dir_util.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cexts/_distutils/errors.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cexts/_distutils/extension.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cexts/_distutils/file_util.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cexts/_distutils/modified.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cexts/_distutils/spawn.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cexts/_distutils/sysconfig.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cexts/_distutils/util.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cexts/_distutils/version.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cexts/build.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cexts/cmake.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cexts/configs.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cexts/importhook.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cexts/magic.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cexts/scan.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/__main__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/cache.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/ci.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/cli.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/compose.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/consts.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/docker/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/docker/buildcaching.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/docker/cache.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/docker/cacheserved/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/docker/cacheserved/cache.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/docker/cacheserved/manifests.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/docker/cmds.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/docker/dataserver.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/docker/imagepulling.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/docker/inject.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/docker/packing.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/docker/repositories.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/docker/utils.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/github/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/github/api/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/github/api/clients.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/github/api/v1/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/github/api/v1/api.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/github/api/v1/client.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/github/api/v2/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/github/api/v2/api.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/github/api/v2/azure.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/github/api/v2/client.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/github/bootstrap.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/github/cache.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/github/cli.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/github/env.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/github/inject.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/inject.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/requirements.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/shell.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/ci/utils.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cli/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cli/__main__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cli/_pathhack.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cli/clicli.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cli/install.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cli/main.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cli/managers.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cli/types.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/clipboard/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/clipboard/capi/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/clipboard/capi/darwin_cf.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/clipboard/capi/linux_x11.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/clipboard/commands.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/clipboard/platform.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/clipboard/types.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cmake.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cmdlog/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cmdlog/__main__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cmdlog/_cmdlog.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cmdlog/cli.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/cmdlog/cmdlog.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dataclasses/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dataclasses/__main__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dataclasses/_dumping.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dataclasses/_template.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dataclasses/cli.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dataclasses/codegen.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dataclasses/dumping.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dataserver/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dataserver/handlers.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dataserver/http.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dataserver/routes.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dataserver/server.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dataserver/targets.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/diffs/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/diffs/__main__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/diffs/cli.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/diffs/parsing.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/diffs/rendering.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/diffs/types.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/__main__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/build.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/cli.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/config.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/config.toml +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/content.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/discovery.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/gen.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/helpers.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/ops.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/rendering.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/resources/configs/.gdbinit +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/resources/configs/.sqliterc +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/resources/configs/.tmux.conf +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/resources/configs/.vimrc +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/resources/depsets/python.toml +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/resources/depsets/system.toml +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/resources/depsets/x11.toml +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/resources/fragments/apt.sh +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/resources/fragments/chgrp.sh +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/resources/fragments/docker.sh +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/resources/fragments/firefox.sh +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/resources/fragments/go.sh +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/resources/fragments/jdk.sh +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/resources/fragments/man.sh +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/resources/fragments/nvm.sh +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/resources/fragments/om.sh +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/resources/fragments/pyenv.sh +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/resources/fragments/rbenv.sh +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/resources/fragments/rust.sh +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/resources/fragments/sshd.sh +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/resources/fragments/user.sh +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/resources/fragments/uv.sh +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/resources/fragments/vcpkg.sh +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/resources/fragments/workdir.sh +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/resources/fragments/zig.sh +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/resources/scripts/install-claude +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/resources/scripts/install-codex +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/resources/scripts/install-pi +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/resources/scripts/run-dbus +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/resources/scripts/run-mysql +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/resources/scripts/run-postgres +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/resources/shift-uid.sh +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/run.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/dockerdev/utils.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/git/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/git/magic.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/git/revisions.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/git/shallow.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/git/status.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/git/vendor/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/git/vendor/aborting.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/git/vendor/diffing.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/git/vendor/errors.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/git/vendor/journals.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/git/vendor/merging.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/git/vendor/paths.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/git/vendor/pulling.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/git/vendor/runners.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/git/vendor/specs.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/git/vendor/upstreams.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/home/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/home/__main__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/home/cli.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/home/paths.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/home/secrets.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/home/shadow.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/imgur.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/intellij/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/intellij/cli.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/intellij/ides.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/intellij/open.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/interp/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/interp/__main__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/interp/cli.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/interp/default.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/interp/inject.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/interp/inspect.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/interp/providers/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/interp/providers/base.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/interp/providers/inject.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/interp/providers/running.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/interp/providers/standalone.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/interp/providers/system.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/interp/pyenv/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/interp/pyenv/inject.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/interp/pyenv/install.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/interp/pyenv/provider.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/interp/pyenv/pyenv.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/interp/resolvers.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/interp/types.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/interp/uv/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/interp/uv/inject.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/interp/uv/provider.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/interp/uv/uv.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/interp/venvs.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/java/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/java/__main__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/java/cli.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/java/pomgen.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/java/utils.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/java/xml.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/js/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/js/quickjs/LICENSE +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/js/quickjs/TODO.md +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/js/quickjs/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/js/quickjs/_pyqjsng.c +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/js/quickjs/_pyqjsng.pyi +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/js/quickjs/_quickjs/LICENSE +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/js/quickjs/_quickjs/builtin-array-fromasync.h +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/js/quickjs/_quickjs/builtin-iterator-zip-keyed.h +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/js/quickjs/_quickjs/builtin-iterator-zip.h +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/js/quickjs/_quickjs/cutils.h +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/js/quickjs/_quickjs/dtoa.c +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/js/quickjs/_quickjs/dtoa.h +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/js/quickjs/_quickjs/libregexp-opcode.h +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/js/quickjs/_quickjs/libregexp.c +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/js/quickjs/_quickjs/libregexp.h +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/js/quickjs/_quickjs/libunicode-table.h +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/js/quickjs/_quickjs/libunicode.c +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/js/quickjs/_quickjs/libunicode.h +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/js/quickjs/_quickjs/list.h +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/js/quickjs/_quickjs/quickjs-atom.h +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/js/quickjs/_quickjs/quickjs-c-atomics.h +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/js/quickjs/_quickjs/quickjs-libc.c +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/js/quickjs/_quickjs/quickjs-libc.h +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/js/quickjs/_quickjs/quickjs-opcode.h +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/js/quickjs/_quickjs/quickjs.c +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/js/quickjs/_quickjs/quickjs.h +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/js/quickjs/snapshots.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/magic/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/magic/__main__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/magic/cli.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/magic/find.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/magic/magic.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/magic/prepare.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/magic/styles.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/manifests/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/manifests/__main__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/manifests/_dumping.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/manifests/building.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/manifests/dumping.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/manifests/main.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/markdownit/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/markdownit/incparse.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/markdownit/tokens.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/mypy/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/mypy/debug.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/mypy/report.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/packaging/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/packaging/marshal.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/packaging/names.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/packaging/requirements.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/packaging/revisions.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/packaging/specifiers.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/packaging/versions.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/packaging/wheelfile.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/pip.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/precheck/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/precheck/__main__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/precheck/base.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/precheck/blanklines.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/precheck/caches.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/precheck/git.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/precheck/imports.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/precheck/lite.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/precheck/main.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/precheck/manifests.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/precheck/scripts.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/precheck/unicode.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/py/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/py/asts/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/py/asts/parents.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/py/asts/toplevel.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/py/asts/visitors.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/py/attrdocs.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/py/bracepy.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/py/classdot.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/py/docstrings/LICENSE +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/py/docstrings/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/py/docstrings/attrdoc.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/py/docstrings/common.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/py/docstrings/epydoc.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/py/docstrings/google.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/py/docstrings/numpydoc.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/py/docstrings/parser.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/py/docstrings/rest.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/py/findimports.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/py/reprs.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/py/scripts/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/py/scripts/bumpversion.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/py/scripts/importtrace.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/py/srcheaders.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/py/tokens/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/py/tokens/all.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/py/tokens/tokenizert.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/py/tokens/utils.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/py/tools/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/py/tools/fixdocstrings.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/py/tools/importscan.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/py/tools/mkrelimp.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/py/tools/pipdepup.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/py.typed +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/pyproject/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/pyproject/__main__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/pyproject/cli.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/pyproject/configs.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/pyproject/inject.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/pyproject/pkg.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/pyproject/reqs.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/pyproject/resources/dockerdev.sh +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/pyproject/resources/python.sh +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/pyproject/tools/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/pyproject/tools/aboutdeps.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/pyproject/tools/buildrs.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/pyproject/tools/pyversions.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/pyproject/venvs.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/pyproject/versions.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/pyright/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/pyright/report.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/rs/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/scripts/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/scripts/ci.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/scripts/interp.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/scripts/lib/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/scripts/lib/formats/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/scripts/lib/formats/goyaml.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/scripts/lib/inject.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/scripts/lib/io/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/scripts/lib/io/pipelines.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/scripts/lib/io/streambufs.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/scripts/lib/logs.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/scripts/lib/marshal.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/scripts/pidfiles.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/scripts/pyproject.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/irc/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/irc/messages/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/irc/messages/base.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/irc/messages/formats.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/irc/messages/messages.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/irc/messages/parsing.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/irc/numerics/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/irc/numerics/formats.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/irc/numerics/numerics.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/irc/numerics/types.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/irc/protocol/LICENSE +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/irc/protocol/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/irc/protocol/consts.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/irc/protocol/errors.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/irc/protocol/message.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/irc/protocol/nuh.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/irc/protocol/parsing.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/irc/protocol/rendering.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/irc/protocol/tags.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/irc/protocol/utils.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/jsonschema/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/jsonschema/codegen/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/jsonschema/codegen/__main__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/jsonschema/codegen/analysis.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/jsonschema/codegen/cli.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/jsonschema/codegen/config.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/jsonschema/codegen/errors.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/jsonschema/codegen/generator.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/jsonschema/codegen/ir.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/jsonschema/codegen/names.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/jsonschema/codegen/rendering.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/jsonschema/codegen/transforms.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/jsonschema/codegen/typing.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/oci/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/oci/building.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/oci/compression.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/oci/data.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/oci/datarefs.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/oci/dataserver.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/oci/loading.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/oci/media.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/oci/pack/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/oci/pack/packing.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/oci/pack/repositories.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/oci/pack/unpacking.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/oci/repositories.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/specs/oci/tars.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tagstrings.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/cloc.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/diff.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/doc.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/docker.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/git/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/git/__main__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/git/cli.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/git/cloning.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/git/consts.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/git/messages.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/json/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/json/__main__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/json/cli.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/json/formats.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/json/io.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/json/parsing.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/json/processing.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/json/rendering.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/jsonview/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/jsonview/__main__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/jsonview/cli.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/jsonview/resources/jsonview.css +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/jsonview/resources/jsonview.html.j2 +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/jsonview/resources/jsonview.js +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/linehisto.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/mkenv.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/notebook.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/ocr.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/pawk/README.md +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/pawk/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/pawk/__main__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/pawk/pawk.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/pip.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/prof.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/qr.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/shadow.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/shell.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tools/sqlrepl.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/_devdocs/design.md +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/_devdocs/dev_00_initial.md +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/_devdocs/intro.md +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/_devdocs/requirements.md +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/_devdocs/research.md +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/controls/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/controls/base.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/controls/cards.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/controls/history.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/controls/markdown.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/controls/spinners.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/controls/stacks.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/controls/static.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/controls/status.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/controls/suggestions.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/docs/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/docs/cursors.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/docs/documents.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/docs/edits.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/docs/highlighting.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/docs/searching.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/docs/treesitter.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/events/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/events/keymaps.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/events/keys.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/events/parsing.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/events/xterm.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/runtime/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/runtime/base.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/runtime/timers.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/screens/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/screens/cells.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/screens/diffs.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/surfaces/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/surfaces/writers.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/text/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/text/colors.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/text/highlights/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/text/highlights/base.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/text/highlights/pygments.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/text/markdown/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/text/markdown/backends.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/text/markdown/base.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/text/markdown/flattening.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/text/markdown/markdownit.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/text/markdown/pdcmark.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/text/parts.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/text/segments.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/text/sgr.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/text/styles.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/text/widths.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/text/wrap.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/tty/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/vim/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/vim/engine.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/vim/modes.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/vim/motions.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/vim/parsing.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/vim/registers.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/vim/scans.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/vim/status.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/vim/substitutes.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/minitui/vim/textobjs.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/rich/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/rich/console2.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/rich/diff/LICENSE +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/rich/diff/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/rich/diff/__main__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/rich/diff/_compat.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/rich/diff/cli.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/rich/diff/renderables.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/rich/diff/rendering.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/rich/diff/underlinebar.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/rich/markdown2.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/rich/textual/__init__.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/rich/textual/dark.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/rich/textual/dump.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/rich/textual/themes.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev/tui/rich/trirule.py +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev.egg-info/dependency_links.txt +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev.egg-info/entry_points.txt +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/omdev.egg-info/top_level.txt +0 -0
- {omdev-0.0.51 → omdev-0.0.52}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: omdev
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.52
|
|
4
4
|
Summary: omdev
|
|
5
5
|
Author: wrmsr
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -14,11 +14,11 @@ Classifier: Programming Language :: Python :: 3.15
|
|
|
14
14
|
Requires-Python: >=3.14
|
|
15
15
|
Description-Content-Type: text/markdown
|
|
16
16
|
License-File: LICENSE
|
|
17
|
-
Requires-Dist: omcore==0.0.
|
|
17
|
+
Requires-Dist: omcore==0.0.52
|
|
18
18
|
Provides-Extra: ominfra
|
|
19
|
-
Requires-Dist: ominfra==0.0.
|
|
19
|
+
Requires-Dist: ominfra==0.0.52; extra == "ominfra"
|
|
20
20
|
Provides-Extra: omllm
|
|
21
|
-
Requires-Dist: omllm==0.0.
|
|
21
|
+
Requires-Dist: omllm==0.0.52; extra == "omllm"
|
|
22
22
|
Provides-Extra: black
|
|
23
23
|
Requires-Dist: black~=26.5; extra == "black"
|
|
24
24
|
Provides-Extra: c
|
|
@@ -64,14 +64,14 @@ Requires-Dist: tree-sitter-toml~=0.7; extra == "tui-syntax"
|
|
|
64
64
|
Requires-Dist: tree-sitter-xml~=0.7; extra == "tui-syntax"
|
|
65
65
|
Requires-Dist: tree-sitter-yaml~=0.7; extra == "tui-syntax"
|
|
66
66
|
Provides-Extra: cext
|
|
67
|
-
Requires-Dist: omdev-cext==0.0.
|
|
67
|
+
Requires-Dist: omdev-cext==0.0.52; extra == "cext"
|
|
68
68
|
Provides-Extra: rs
|
|
69
|
-
Requires-Dist: omdev-rs==0.0.
|
|
69
|
+
Requires-Dist: omdev-rs==0.0.52; extra == "rs"
|
|
70
70
|
Provides-Extra: cli
|
|
71
|
-
Requires-Dist: omdev-cli==0.0.
|
|
71
|
+
Requires-Dist: omdev-cli==0.0.52; extra == "cli"
|
|
72
72
|
Provides-Extra: all
|
|
73
|
-
Requires-Dist: ominfra==0.0.
|
|
74
|
-
Requires-Dist: omllm==0.0.
|
|
73
|
+
Requires-Dist: ominfra==0.0.52; extra == "all"
|
|
74
|
+
Requires-Dist: omllm==0.0.52; extra == "all"
|
|
75
75
|
Requires-Dist: black~=26.5; extra == "all"
|
|
76
76
|
Requires-Dist: pycparser~=3.0; extra == "all"
|
|
77
77
|
Requires-Dist: pcpp~=1.30; extra == "all"
|
|
@@ -104,9 +104,9 @@ Requires-Dist: tree-sitter-sql~=0.3; extra == "all"
|
|
|
104
104
|
Requires-Dist: tree-sitter-toml~=0.7; extra == "all"
|
|
105
105
|
Requires-Dist: tree-sitter-xml~=0.7; extra == "all"
|
|
106
106
|
Requires-Dist: tree-sitter-yaml~=0.7; extra == "all"
|
|
107
|
-
Requires-Dist: omdev-cext==0.0.
|
|
108
|
-
Requires-Dist: omdev-rs==0.0.
|
|
109
|
-
Requires-Dist: omdev-cli==0.0.
|
|
107
|
+
Requires-Dist: omdev-cext==0.0.52; extra == "all"
|
|
108
|
+
Requires-Dist: omdev-rs==0.0.52; extra == "all"
|
|
109
|
+
Requires-Dist: omdev-cli==0.0.52; extra == "all"
|
|
110
110
|
Dynamic: license-file
|
|
111
111
|
|
|
112
112
|
# Overview
|
|
@@ -319,7 +319,7 @@
|
|
|
319
319
|
"module": ".scripts.slowcat",
|
|
320
320
|
"attr": "_CLI_MODULE",
|
|
321
321
|
"file": "omdev/scripts/slowcat.py",
|
|
322
|
-
"line":
|
|
322
|
+
"line": 120,
|
|
323
323
|
"value": {
|
|
324
324
|
"!.cli.types.CliModule": {
|
|
325
325
|
"name": "slowcat",
|
|
@@ -331,7 +331,7 @@
|
|
|
331
331
|
"module": ".scripts.tmpexec",
|
|
332
332
|
"attr": "_CLI_MODULE",
|
|
333
333
|
"file": "omdev/scripts/tmpexec.py",
|
|
334
|
-
"line":
|
|
334
|
+
"line": 53,
|
|
335
335
|
"value": {
|
|
336
336
|
"!.cli.types.CliModule": {
|
|
337
337
|
"name": "tmpexec",
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
"14d": "3.14.7d",
|
|
13
13
|
"14t": "3.14.7t",
|
|
14
14
|
"14dt": "3.14.7dt",
|
|
15
|
-
"15": "3.15.
|
|
16
|
-
"15d": "3.15.
|
|
17
|
-
"15t": "3.15.
|
|
18
|
-
"15dt": "3.15.
|
|
15
|
+
"15": "3.15.0rc2",
|
|
16
|
+
"15d": "3.15.0rc2d",
|
|
17
|
+
"15t": "3.15.0rc2t",
|
|
18
|
+
"15dt": "3.15.0rc2dt"
|
|
19
19
|
}
|
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# @om-script
|
|
3
|
+
# @om-precheck-allow-any-unicode
|
|
4
|
+
"""
|
|
5
|
+
Pure-stdlib JUnit XML -> GitHub Actions job summary + optional annotations.
|
|
6
|
+
|
|
7
|
+
====
|
|
8
|
+
|
|
9
|
+
https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-commands
|
|
10
|
+
"""
|
|
11
|
+
import argparse
|
|
12
|
+
import collections
|
|
13
|
+
import dataclasses as dc
|
|
14
|
+
import glob
|
|
15
|
+
import os
|
|
16
|
+
import pathlib
|
|
17
|
+
import sys
|
|
18
|
+
import typing as ta
|
|
19
|
+
import xml.etree.ElementTree as ET
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
##
|
|
23
|
+
# GitHub Actions helpers
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _gha_escape_data(s: object) -> str:
|
|
27
|
+
# Escaping convention used by the Actions command protocol.
|
|
28
|
+
return (
|
|
29
|
+
str(s)
|
|
30
|
+
.replace('%', '%25')
|
|
31
|
+
.replace('\r', '%0D')
|
|
32
|
+
.replace('\n', '%0A')
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _gha_escape_prop(s: object) -> str:
|
|
37
|
+
return (
|
|
38
|
+
_gha_escape_data(s)
|
|
39
|
+
.replace(':', '%3A')
|
|
40
|
+
.replace(',', '%2C')
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def gha_command(name: str, message: str = '', **props: object) -> None:
|
|
45
|
+
"""
|
|
46
|
+
Emit a GitHub Actions workflow command to stdout.
|
|
47
|
+
|
|
48
|
+
Example:
|
|
49
|
+
gha_command("error", "boom", file="tests/test_foo.py", line=12)
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
prop_s = ''
|
|
53
|
+
clean_props = {k: v for k, v in props.items() if v is not None and v != ''}
|
|
54
|
+
if clean_props:
|
|
55
|
+
prop_s = ' ' + ','.join(
|
|
56
|
+
f'{k}={_gha_escape_prop(v)}'
|
|
57
|
+
for k, v in clean_props.items()
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
print(f'::{name}{prop_s}::{_gha_escape_data(message)}', flush=True)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def append_step_summary(markdown: str) -> bool:
|
|
64
|
+
"""
|
|
65
|
+
Append Markdown to GITHUB_STEP_SUMMARY when running in GitHub Actions.
|
|
66
|
+
|
|
67
|
+
Returns True if written to the summary file, False if not in GHA.
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
path = os.environ.get('GITHUB_STEP_SUMMARY')
|
|
71
|
+
if not path:
|
|
72
|
+
return False
|
|
73
|
+
|
|
74
|
+
with open(path, 'a', encoding='utf-8') as f:
|
|
75
|
+
f.write(markdown)
|
|
76
|
+
if not markdown.endswith('\n'):
|
|
77
|
+
f.write('\n')
|
|
78
|
+
return True
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
##
|
|
82
|
+
# JUnit parsing
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
@dc.dataclass(frozen=True)
|
|
86
|
+
class TestCase:
|
|
87
|
+
source: pathlib.Path
|
|
88
|
+
suite: str
|
|
89
|
+
classname: str
|
|
90
|
+
name: str
|
|
91
|
+
time: float
|
|
92
|
+
status: str # passed | failure | error | skipped
|
|
93
|
+
message: str = ''
|
|
94
|
+
details: str = ''
|
|
95
|
+
file: str = ''
|
|
96
|
+
line: int | None = None
|
|
97
|
+
|
|
98
|
+
@property
|
|
99
|
+
def display_name(self) -> str:
|
|
100
|
+
if self.classname:
|
|
101
|
+
return f'{self.classname}.{self.name}'
|
|
102
|
+
return self.name
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def _local_name(tag: str) -> str:
|
|
106
|
+
return tag.rsplit('}', 1)[-1]
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _float_attr(el: ET.Element, name: str, default: float = 0.0) -> float:
|
|
110
|
+
try:
|
|
111
|
+
return float(el.get(name, default))
|
|
112
|
+
except (TypeError, ValueError):
|
|
113
|
+
return default
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def _int_attr_any(el: ET.Element, names: ta.Iterable[str]) -> int | None:
|
|
117
|
+
for name in names:
|
|
118
|
+
raw = el.get(name)
|
|
119
|
+
if raw is None or raw == '':
|
|
120
|
+
continue
|
|
121
|
+
try:
|
|
122
|
+
return int(raw)
|
|
123
|
+
except ValueError:
|
|
124
|
+
continue
|
|
125
|
+
return None
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def _first_direct_child(el: ET.Element, *names: str) -> ET.Element | None:
|
|
129
|
+
wanted = set(names)
|
|
130
|
+
for child in list(el):
|
|
131
|
+
if _local_name(child.tag) in wanted:
|
|
132
|
+
return child
|
|
133
|
+
return None
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def _all_text(el: ET.Element | None) -> str:
|
|
137
|
+
if el is None:
|
|
138
|
+
return ''
|
|
139
|
+
return ''.join(el.itertext()).strip()
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def _preview(s: str, n: int = 300) -> str:
|
|
143
|
+
s = ' '.join(s.split())
|
|
144
|
+
if len(s) <= n:
|
|
145
|
+
return s
|
|
146
|
+
return s[: n - 1] + '…'
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def iter_testsuites(root: ET.Element) -> ta.Iterator[ET.Element]:
|
|
150
|
+
if _local_name(root.tag) == 'testsuite':
|
|
151
|
+
yield root
|
|
152
|
+
|
|
153
|
+
for el in root.iter():
|
|
154
|
+
if el is root:
|
|
155
|
+
continue
|
|
156
|
+
if _local_name(el.tag) == 'testsuite':
|
|
157
|
+
yield el
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def parse_junit_file(path: pathlib.Path) -> list[TestCase]:
|
|
161
|
+
root = ET.parse(path).getroot() # noqa # FIXME: defuesedxml?
|
|
162
|
+
out: list[TestCase] = []
|
|
163
|
+
|
|
164
|
+
for suite_el in iter_testsuites(root):
|
|
165
|
+
suite_name = suite_el.get('name') or path.name
|
|
166
|
+
|
|
167
|
+
# JUnit normally has testcases as direct children of testsuite.
|
|
168
|
+
for tc_el in list(suite_el):
|
|
169
|
+
if _local_name(tc_el.tag) != 'testcase':
|
|
170
|
+
continue
|
|
171
|
+
|
|
172
|
+
classname = tc_el.get('classname') or ''
|
|
173
|
+
name = tc_el.get('name') or '<unnamed>'
|
|
174
|
+
time = _float_attr(tc_el, 'time')
|
|
175
|
+
|
|
176
|
+
status = 'passed'
|
|
177
|
+
problem_el = _first_direct_child(tc_el, 'error')
|
|
178
|
+
if problem_el is not None:
|
|
179
|
+
status = 'error'
|
|
180
|
+
else:
|
|
181
|
+
problem_el = _first_direct_child(tc_el, 'failure')
|
|
182
|
+
if problem_el is not None:
|
|
183
|
+
status = 'failure'
|
|
184
|
+
else:
|
|
185
|
+
problem_el = _first_direct_child(tc_el, 'skipped')
|
|
186
|
+
if problem_el is not None:
|
|
187
|
+
status = 'skipped'
|
|
188
|
+
|
|
189
|
+
details = _all_text(problem_el)
|
|
190
|
+
message = ''
|
|
191
|
+
if problem_el is not None:
|
|
192
|
+
message = (
|
|
193
|
+
problem_el.get('message')
|
|
194
|
+
or problem_el.get('type')
|
|
195
|
+
or _preview(details)
|
|
196
|
+
or status
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
out.append(TestCase(
|
|
200
|
+
source=path,
|
|
201
|
+
suite=suite_name,
|
|
202
|
+
classname=classname,
|
|
203
|
+
name=name,
|
|
204
|
+
time=time,
|
|
205
|
+
status=status,
|
|
206
|
+
message=message,
|
|
207
|
+
details=details,
|
|
208
|
+
file=tc_el.get('file') or '',
|
|
209
|
+
line=_int_attr_any(tc_el, ('line', 'lineno')),
|
|
210
|
+
))
|
|
211
|
+
|
|
212
|
+
return out
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def expand_paths(patterns: list[str]) -> list[pathlib.Path]:
|
|
216
|
+
paths: list[pathlib.Path] = []
|
|
217
|
+
for pattern in patterns:
|
|
218
|
+
matches = glob.glob(pattern, recursive=True)
|
|
219
|
+
if matches:
|
|
220
|
+
paths.extend(pathlib.Path(m) for m in matches)
|
|
221
|
+
else:
|
|
222
|
+
paths.append(pathlib.Path(pattern))
|
|
223
|
+
|
|
224
|
+
seen: set[pathlib.Path] = set()
|
|
225
|
+
out: list[pathlib.Path] = []
|
|
226
|
+
for p in paths:
|
|
227
|
+
p = p.resolve()
|
|
228
|
+
if p not in seen:
|
|
229
|
+
seen.add(p)
|
|
230
|
+
out.append(p)
|
|
231
|
+
return out
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
##
|
|
235
|
+
# Markdown rendering
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def md_cell(s: object) -> str:
|
|
239
|
+
"""Escape enough for GitHub Markdown tables."""
|
|
240
|
+
|
|
241
|
+
return (
|
|
242
|
+
str(s)
|
|
243
|
+
.replace('\\', '\\\\')
|
|
244
|
+
.replace('|', '\\|')
|
|
245
|
+
.replace('\r', '')
|
|
246
|
+
.replace('\n', '<br>')
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def fmt_time(seconds: float) -> str:
|
|
251
|
+
if seconds < 1:
|
|
252
|
+
return f'{seconds * 1000:.0f} ms'
|
|
253
|
+
if seconds < 60:
|
|
254
|
+
return f'{seconds:.2f} s'
|
|
255
|
+
m, s = divmod(seconds, 60)
|
|
256
|
+
return f'{int(m)}m {s:.1f}s'
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
def fenced(text: str, lang: str = 'text') -> str:
|
|
260
|
+
fence = '```'
|
|
261
|
+
while fence in text:
|
|
262
|
+
fence += '`'
|
|
263
|
+
return f'{fence}{lang}\n{text.rstrip()}\n{fence}'
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def count_status(cases: list[TestCase]) -> dict[str, int]:
|
|
267
|
+
d = {
|
|
268
|
+
'passed': 0,
|
|
269
|
+
'failure': 0,
|
|
270
|
+
'error': 0,
|
|
271
|
+
'skipped': 0,
|
|
272
|
+
}
|
|
273
|
+
for c in cases:
|
|
274
|
+
d[c.status] = d.get(c.status, 0) + 1
|
|
275
|
+
return d
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
def render_summary(
|
|
279
|
+
cases: list[TestCase],
|
|
280
|
+
sources: list[pathlib.Path],
|
|
281
|
+
*,
|
|
282
|
+
max_failures: int = 25,
|
|
283
|
+
max_detail_chars: int = 4000,
|
|
284
|
+
) -> str:
|
|
285
|
+
counts = count_status(cases)
|
|
286
|
+
total = len(cases)
|
|
287
|
+
bad = counts['failure'] + counts['error']
|
|
288
|
+
passed = counts['passed']
|
|
289
|
+
skipped = counts['skipped']
|
|
290
|
+
total_time = sum(c.time for c in cases)
|
|
291
|
+
|
|
292
|
+
icon = '✅' if bad == 0 else '❌'
|
|
293
|
+
pass_rate = 100.0 * passed / total if total else 0.0
|
|
294
|
+
|
|
295
|
+
lines: list[str] = []
|
|
296
|
+
lines.append(f'## {icon} Test results')
|
|
297
|
+
lines.append('')
|
|
298
|
+
lines.append('| Total | Passed | Failed | Errors | Skipped | Pass rate | Time |')
|
|
299
|
+
lines.append('|---:|---:|---:|---:|---:|---:|---:|')
|
|
300
|
+
lines.append(
|
|
301
|
+
f"| {total} | {passed} | {counts['failure']} | {counts['error']} | "
|
|
302
|
+
f"{skipped} | {pass_rate:.1f}% | {fmt_time(total_time)} |",
|
|
303
|
+
)
|
|
304
|
+
lines.append('')
|
|
305
|
+
|
|
306
|
+
if sources:
|
|
307
|
+
lines.append('<details>')
|
|
308
|
+
lines.append('<summary>JUnit XML files</summary>')
|
|
309
|
+
lines.append('')
|
|
310
|
+
for p in sources:
|
|
311
|
+
lines.append(f'- `{p}`')
|
|
312
|
+
lines.append('')
|
|
313
|
+
lines.append('</details>')
|
|
314
|
+
lines.append('')
|
|
315
|
+
|
|
316
|
+
by_suite: dict[str, list[TestCase]] = collections.defaultdict(list)
|
|
317
|
+
for c in cases:
|
|
318
|
+
by_suite[c.suite].append(c)
|
|
319
|
+
|
|
320
|
+
if by_suite:
|
|
321
|
+
lines.append('### Suites')
|
|
322
|
+
lines.append('')
|
|
323
|
+
lines.append('| Suite | Total | Passed | Failed | Errors | Skipped | Time |')
|
|
324
|
+
lines.append('|---|---:|---:|---:|---:|---:|---:|')
|
|
325
|
+
|
|
326
|
+
def suite_sort_key(item: tuple[str, list[TestCase]]) -> tuple[int, int, str]:
|
|
327
|
+
name, suite_cases = item
|
|
328
|
+
sc = count_status(suite_cases)
|
|
329
|
+
return (-(sc['failure'] + sc['error']), -len(suite_cases), name)
|
|
330
|
+
|
|
331
|
+
for suite, suite_cases in sorted(by_suite.items(), key=suite_sort_key):
|
|
332
|
+
sc = count_status(suite_cases)
|
|
333
|
+
lines.append(
|
|
334
|
+
f"| {md_cell(suite)} | {len(suite_cases)} | {sc['passed']} | "
|
|
335
|
+
f"{sc['failure']} | {sc['error']} | {sc['skipped']} | "
|
|
336
|
+
f"{fmt_time(sum(c.time for c in suite_cases))} |",
|
|
337
|
+
)
|
|
338
|
+
lines.append('')
|
|
339
|
+
|
|
340
|
+
failed_cases = [c for c in cases if c.status in {'failure', 'error'}]
|
|
341
|
+
if failed_cases:
|
|
342
|
+
shown = failed_cases[:max_failures]
|
|
343
|
+
|
|
344
|
+
lines.append('### Failed tests')
|
|
345
|
+
lines.append('')
|
|
346
|
+
lines.append('| Status | Test | Message | Location |')
|
|
347
|
+
lines.append('|---|---|---|---|')
|
|
348
|
+
|
|
349
|
+
for c in shown:
|
|
350
|
+
location = ''
|
|
351
|
+
if c.file:
|
|
352
|
+
location = c.file
|
|
353
|
+
if c.line:
|
|
354
|
+
location += f':{c.line}'
|
|
355
|
+
|
|
356
|
+
lines.append(
|
|
357
|
+
f'| {md_cell(c.status)} | `{md_cell(c.display_name)}` | '
|
|
358
|
+
f'{md_cell(_preview(c.message, 500))} | {md_cell(location)} |',
|
|
359
|
+
)
|
|
360
|
+
|
|
361
|
+
if len(failed_cases) > len(shown):
|
|
362
|
+
lines.append('')
|
|
363
|
+
lines.append(f'_Showing {len(shown)} of {len(failed_cases)} failing tests._')
|
|
364
|
+
|
|
365
|
+
lines.append('')
|
|
366
|
+
lines.append('<details>')
|
|
367
|
+
lines.append('<summary>Failure details</summary>')
|
|
368
|
+
lines.append('')
|
|
369
|
+
|
|
370
|
+
for c in shown:
|
|
371
|
+
lines.append(f'#### `{c.display_name}`')
|
|
372
|
+
lines.append('')
|
|
373
|
+
if c.file:
|
|
374
|
+
loc = c.file + (f':{c.line}' if c.line else '')
|
|
375
|
+
lines.append(f'`{loc}`')
|
|
376
|
+
lines.append('')
|
|
377
|
+
|
|
378
|
+
detail = c.details or c.message
|
|
379
|
+
if len(detail) > max_detail_chars:
|
|
380
|
+
detail = detail[:max_detail_chars] + '\n… truncated …'
|
|
381
|
+
|
|
382
|
+
lines.append(fenced(detail))
|
|
383
|
+
lines.append('')
|
|
384
|
+
|
|
385
|
+
lines.append('</details>')
|
|
386
|
+
lines.append('')
|
|
387
|
+
|
|
388
|
+
return '\n'.join(lines).rstrip() + '\n'
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
##
|
|
392
|
+
# Annotations
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
def emit_failure_annotations(cases: list[TestCase], *, max_annotations: int) -> None:
|
|
396
|
+
n = 0
|
|
397
|
+
for c in cases:
|
|
398
|
+
if c.status not in {'failure', 'error'}:
|
|
399
|
+
continue
|
|
400
|
+
if n >= max_annotations:
|
|
401
|
+
gha_command(
|
|
402
|
+
'warning',
|
|
403
|
+
f'Not emitting further test annotations; hit max_annotations={max_annotations}',
|
|
404
|
+
title='JUnit summary',
|
|
405
|
+
)
|
|
406
|
+
return
|
|
407
|
+
|
|
408
|
+
gha_command(
|
|
409
|
+
'error',
|
|
410
|
+
c.message or c.status,
|
|
411
|
+
title=f'{c.status}: {c.display_name}',
|
|
412
|
+
file=c.file or None,
|
|
413
|
+
line=c.line,
|
|
414
|
+
)
|
|
415
|
+
n += 1
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
##
|
|
419
|
+
# Main
|
|
420
|
+
|
|
421
|
+
|
|
422
|
+
def main(argv: list[str]) -> int:
|
|
423
|
+
ap = argparse.ArgumentParser()
|
|
424
|
+
ap.add_argument('xml', nargs='+', help='JUnit XML path(s) or glob(s)')
|
|
425
|
+
ap.add_argument('--annotations', action='store_true')
|
|
426
|
+
ap.add_argument('--max-annotations', type=int, default=50)
|
|
427
|
+
ap.add_argument('--max-failures', type=int, default=25)
|
|
428
|
+
ap.add_argument('--fail-on-failure', action='store_true')
|
|
429
|
+
ap.add_argument('--allow-missing', action='store_true')
|
|
430
|
+
ns = ap.parse_args(argv)
|
|
431
|
+
|
|
432
|
+
paths = expand_paths(ns.xml)
|
|
433
|
+
existing = [p for p in paths if p.exists()]
|
|
434
|
+
|
|
435
|
+
if not existing:
|
|
436
|
+
msg = 'No JUnit XML files found: ' + ', '.join(ns.xml)
|
|
437
|
+
if ns.allow_missing:
|
|
438
|
+
gha_command('warning', msg, title='JUnit summary')
|
|
439
|
+
append_step_summary(f'## ⚠️ Test results\n\n{msg}\n')
|
|
440
|
+
return 0
|
|
441
|
+
gha_command('error', msg, title='JUnit summary')
|
|
442
|
+
return 2
|
|
443
|
+
|
|
444
|
+
cases: list[TestCase] = []
|
|
445
|
+
parse_errors: list[tuple[pathlib.Path, Exception]] = []
|
|
446
|
+
|
|
447
|
+
for p in existing:
|
|
448
|
+
try:
|
|
449
|
+
cases.extend(parse_junit_file(p))
|
|
450
|
+
except Exception as ex: # noqa
|
|
451
|
+
parse_errors.append((p, ex))
|
|
452
|
+
|
|
453
|
+
if parse_errors:
|
|
454
|
+
for p, e in parse_errors:
|
|
455
|
+
gha_command('error', f'{type(e).__name__}: {e}', title='Failed to parse JUnit XML', file=str(p))
|
|
456
|
+
return 2
|
|
457
|
+
|
|
458
|
+
if ns.annotations:
|
|
459
|
+
emit_failure_annotations(cases, max_annotations=ns.max_annotations)
|
|
460
|
+
|
|
461
|
+
markdown = render_summary(cases, existing, max_failures=ns.max_failures)
|
|
462
|
+
wrote_summary = append_step_summary(markdown)
|
|
463
|
+
|
|
464
|
+
# Useful when running locally.
|
|
465
|
+
if not wrote_summary:
|
|
466
|
+
print(markdown)
|
|
467
|
+
|
|
468
|
+
counts = count_status(cases)
|
|
469
|
+
bad = counts['failure'] + counts['error']
|
|
470
|
+
if ns.fail_on_failure and bad:
|
|
471
|
+
return 1
|
|
472
|
+
|
|
473
|
+
return 0
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
if __name__ == '__main__':
|
|
477
|
+
raise SystemExit(main(sys.argv[1:]))
|
|
@@ -11,12 +11,12 @@ Built primarily for llm coding-agent chat TUIs, deliberately generalized for any
|
|
|
11
11
|
## Try it
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
./python -m omdev.tui.minitui.apps.chatdemo # streaming markdown chat: tool cards (f10/f2), /help, history, search
|
|
15
|
-
./python -m omdev.tui.minitui.apps.chatdemo --md=pdcmark # swap the streaming markdown backend (internal|pdcmark|markdown-it)
|
|
16
|
-
./python -m omdev.tui.minitui.apps.chatdemo --mouse # + click-to-expand cards / click suggestions (trades wheel scrollback)
|
|
17
|
-
./python -m omdev.tui.minitui.apps.inputdemo # minimal typing-while-streaming proof
|
|
18
|
-
./python -m omdev.tui.minitui.apps.streamdemo # the bare commit model, no input
|
|
19
|
-
./python -m omdev.tui.minitui.apps.vimdemo f.py # fullscreen vim clone (:w/:q, ctrl+v blocks, %/~/zz), tree-sitter highlighted
|
|
14
|
+
./python -m omdev.tui.minitui.tests.apps.chatdemo # streaming markdown chat: tool cards (f10/f2), /help, history, search
|
|
15
|
+
./python -m omdev.tui.minitui.tests.apps.chatdemo --md=pdcmark # swap the streaming markdown backend (internal|pdcmark|markdown-it)
|
|
16
|
+
./python -m omdev.tui.minitui.tests.apps.chatdemo --mouse # + click-to-expand cards / click suggestions (trades wheel scrollback)
|
|
17
|
+
./python -m omdev.tui.minitui.tests.apps.inputdemo # minimal typing-while-streaming proof
|
|
18
|
+
./python -m omdev.tui.minitui.tests.apps.streamdemo # the bare commit model, no input
|
|
19
|
+
./python -m omdev.tui.minitui.tests.apps.vimdemo f.py # fullscreen vim clone (:w/:q, :set nu, ctrl+v blocks, %/~/zz), tree-sitter highlighted
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
Run them in tmux and scroll back; add `--visualize-redraws` to streamdemo to watch damage regions.
|
|
@@ -42,12 +42,13 @@ Run them in tmux and scroll back; add `--visualize-redraws` to streamdemo to wat
|
|
|
42
42
|
undo/redo, CMDLINE mode with incremental search, blockwise visual (ctrl+v) with live multi-cursor I/A/c replication,
|
|
43
43
|
`%`/`~`, `status()`/`decorations()` as its only outputs. Never renders, never reads a keyboard.
|
|
44
44
|
- **controls/** - small and passive: `TextArea` (a scrolled vim window - grows to a max height, then the viewport
|
|
45
|
-
follows the cursor; optional syntax highlighting under engine decorations; ctrl+d/u, zz/zt/zb, H/M/L viewport ops
|
|
46
|
-
status bar, statics, spinner, suggestions popup, markdown tail, lifecycle cards, input
|
|
47
|
-
mouse hit regions.
|
|
45
|
+
follows the cursor; optional syntax highlighting under engine decorations; ctrl+d/u, zz/zt/zb, H/M/L viewport ops;
|
|
46
|
+
vim's line number column), status bar, statics, spinner, suggestions popup, markdown tail, lifecycle cards, input
|
|
47
|
+
history, stack layout with mouse hit regions.
|
|
48
48
|
- **runtime/** - `SyncDriver` (poll + self-pipe) and `AsyncioDriver` (asyncio; `post()` is the sole thread-safe entry).
|
|
49
49
|
Both share the `App` contract: `render(width, max_height) -> Frame` + `handle_event(event)`, with coalescing
|
|
50
|
-
invalidation.
|
|
50
|
+
invalidation. Both do job control: ctrl+z / SIGTSTP hands the terminal back clean before the stop, SIGCONT re-enters
|
|
51
|
+
application mode and re-anchors the inline origin, and the app sees `SuspendEvent` / `ResumeEvent`.
|
|
51
52
|
|
|
52
53
|
## Notes
|
|
53
54
|
|
|
@@ -47,6 +47,7 @@ with _lang.auto_proxy_init(
|
|
|
47
47
|
)
|
|
48
48
|
|
|
49
49
|
from .controls.textarea import ( # noqa
|
|
50
|
+
LINENR_TAG,
|
|
50
51
|
TextArea,
|
|
51
52
|
)
|
|
52
53
|
|
|
@@ -128,6 +129,8 @@ with _lang.auto_proxy_init(
|
|
|
128
129
|
MouseEvent,
|
|
129
130
|
FocusEvent,
|
|
130
131
|
ResizeEvent,
|
|
132
|
+
SuspendEvent,
|
|
133
|
+
ResumeEvent,
|
|
131
134
|
CursorPositionEvent,
|
|
132
135
|
ModeReportEvent,
|
|
133
136
|
KittyFlagsEvent,
|
|
@@ -164,6 +167,10 @@ with _lang.auto_proxy_init(
|
|
|
164
167
|
App,
|
|
165
168
|
)
|
|
166
169
|
|
|
170
|
+
from .runtime.jobcontrol import ( # noqa
|
|
171
|
+
JobControl,
|
|
172
|
+
)
|
|
173
|
+
|
|
167
174
|
from .runtime.sync import ( # noqa
|
|
168
175
|
SyncDriver,
|
|
169
176
|
)
|