splent-cli 1.52.0__tar.gz → 1.54.0__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.
- {splent_cli-1.52.0/src/splent_cli.egg-info → splent_cli-1.54.0}/PKG-INFO +1 -1
- {splent_cli-1.52.0 → splent_cli-1.54.0}/pyproject.toml +1 -1
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/command/command_create.py +2 -2
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_frontend_init.py +10 -6
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_hook_add.py +7 -6
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_hook_remove.py +10 -6
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_hooks.py +1 -1
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_npm.py +1 -1
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/product_commands.py +7 -1
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/product_frontend_audit.py +9 -5
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/product_test.py +22 -18
- splent_cli-1.54.0/src/splent_cli/commands/product/product_ui_audit.py +233 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/services/own_commands.py +12 -5
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/services/release_workspace.py +43 -0
- splent_cli-1.54.0/src/splent_cli/services/ui_audit.py +483 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_ci_validate.yml.j2 +1 -1
- splent_cli-1.54.0/src/splent_cli/templates/ui_audit/measure.js +226 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/toolchain/frontend/splent/legacy.js +1 -1
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/command_loader.py +10 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/frontend_check.py +1 -1
- {splent_cli-1.52.0 → splent_cli-1.54.0/src/splent_cli.egg-info}/PKG-INFO +1 -1
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli.egg-info/SOURCES.txt +3 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/COPYING +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/COPYING.LESSER +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/README.md +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/setup.cfg +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/__init__.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/__main__.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/cli.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/__init__.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/cache/__init__.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/cache/cache_clear.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/cache/cache_orphans.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/cache/cache_outdated.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/cache/cache_prune.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/cache/cache_size.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/cache/cache_status.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/cache/cache_usage.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/cache/cache_versions.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/check/__init__.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/check/check_contracts.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/check/check_deps.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/check/check_docker.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/check/check_env.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/check/check_features.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/check/check_github.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/check/check_infra.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/check/check_product.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/check/check_pypi.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/check/check_pyproject.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/check/check_releases.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/check/check_vendor.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/clear/__init__.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/clear/clear_build.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/clear/clear_log.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/clear/clear_uploads.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/command/__init__.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/coverage.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/database/db_console.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/database/db_dump.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/database/db_migrate.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/database/db_reset.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/database/db_restore.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/database/db_rollback.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/database/db_seed.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/database/db_status.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/database/db_upgrade.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/doctor.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/env/env_list.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/env/env_set.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/env/env_show.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/export/__init__.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/export/export_puml.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_add.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_attach.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_clean.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_clone.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_compat.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_compile.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_contract.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_create.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_delete.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_detach.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_discard.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_drift.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_env.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_fork.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_git.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_impact.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_info.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_inject_config.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_install.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_list.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_order.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_outdated.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_pin.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_pip_install.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_pull.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_refine.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_release.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_remove.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_rename.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_search.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_security.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_status.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_sync_template.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_test.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_translate.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_unlock.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_upgrade.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_versions.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_xray.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/lint.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/locust.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/marketplace/login.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/marketplace/logout.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/marketplace/marketplace_auth_utils.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/marketplace/marketplace_index.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/marketplace/whoami.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/__init__.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/product_auto_require.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/product_build.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/product_clean.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/product_config.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/product_configure.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/product_console.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/product_containers.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/product_create.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/product_deploy.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/product_derive.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/product_deselect.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/product_down.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/product_drift.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/product_env.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/product_list.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/product_logs.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/product_missing.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/product_params.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/product_port.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/product_release.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/product_resolve.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/product_restart.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/product_routes.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/product_run.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/product_select.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/product_shell.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/product_signals.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/product_sync_template.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/product_up.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/product_validate.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/release/__init__.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/release/release_core.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/release/release_resume.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/selenium.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/spl/__init__.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/spl/spl_add_constraints.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/spl/spl_add_feature.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/spl/spl_compare.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/spl/spl_configurations.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/spl/spl_create.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/spl/spl_deps.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/spl/spl_features.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/spl/spl_fetch.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/spl/spl_info.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/spl/spl_list.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/spl/spl_outdated.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/spl/spl_pin.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/spl/spl_publish.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/spl/spl_remove_feature.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/spl/spl_utils.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/storage/__init__.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/storage/storage_migrate.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/tokens_setup.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/uvl/uvl_utils.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/version.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/services/__init__.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/services/compose.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/services/context.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/services/credentials.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/services/deploy_bundle.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/services/editable_refresh.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/services/frontend.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/services/image_registry.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/services/index_refresh.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/services/marketplace.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/services/marketplace_api.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/services/marketplace_url.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/services/neutral_app.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/services/preflight.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/services/pypi_quota.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/services/registry.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/services/release.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/services/release_dry_run.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/services/release_gate.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/services/security_scan.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/services/source_mirror.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/services/spl_store.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/services/web_container.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_.gitignore.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_MANIFEST.in.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_README.md.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_commands.py.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_config.py.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_docker-compose.dev.yml.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_docker-compose.prod.yml.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_docker.env.example.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_forms.py.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_frontend.npmrc.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_frontend_scripts.js.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_hooks.py.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_init.py.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_init_config.py.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_init_light.py.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_init_service.py.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_migrations_alembic.ini.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_migrations_env.py.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_migrations_script.py.mako.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_models.py.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_pyproject.toml.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_pyproject_minimal.toml.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_repositories.py.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_routes.py.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_scripts.js.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_seeders.py.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_services.py.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_services_service.py.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_signals.py.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_templates_index.html.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_tests_conftest.py.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_tests_e2e.py.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_tests_functional.py.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_tests_integration.py.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_tests_locustfile.py.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_tests_unit.py.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/feature/feature_webpack.config.js.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/licenses/COPYING +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/licenses/COPYING.LESSER +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_.env.dev.example.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_.env.prod.example.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_.gitignore.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_00_core_requirements_dev.sh.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_00_install_features.sh.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_01_compile_assets.sh.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_02_0_db_wait_connection.sh.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_02_1_db_create_db_test.sh.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_02_2_db_create_splent_migrations.sh.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_03_initialize_migrations.sh.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_04_handle_migrations.sh.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_05_0_start_app_dev.sh.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_05_1_start_app_prod.sh.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_400.html +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_401.html +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_404.html +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_500.html +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_Dockerfile.dev.dockerignore.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_Dockerfile.dev.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_Dockerfile.prod.dockerignore.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_Dockerfile.prod.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_README.md.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_app.css +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_app.js +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_base_template.html +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_ci_upgrade.yml.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_config.py.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_docker-compose.dev.yml.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_docker-compose.prod.yml.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_dropzone.css +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_entrypoint.dev.sh.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_entrypoint.prod.sh.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_errors.py.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_favicon.svg +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_init.py.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_logging.py.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_own.css +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_package.json.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_pyproject.toml.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/templates/product/product_uvl.j2 +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/toolchain/Dockerfile.frontend +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/toolchain/frontend/package-lock.json +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/toolchain/frontend/package.json +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/toolchain/frontend/splent/build.js +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/toolchain/frontend/splent/lint.js +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/toolchain/frontend/splent/plugin.js +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/toolchain/frontend/splent/preset.js +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/toolchain/frontend/splent/singletons.json +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/__init__.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/archetype.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/cache_utils.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/ci_services.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/ci_workflow.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/contract_freshness.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/db_client.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/db_utils.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/decorators.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/deploy_freshness.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/dynamic_imports.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/feature_installer.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/feature_naming.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/feature_params.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/feature_requirements.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/feature_resolution.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/feature_utils.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/forge.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/frontend_licenses.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/git_url.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/integrity.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/io_utils.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/lifecycle.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/manifest.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/menu_keys.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/migration_lock.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/npm_semver.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/path_utils.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/proc.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/redact.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/refinement_facts.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/running_version.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/template_drift.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/toml_edit.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/upgrade_plan.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/uvl_diagnosis.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/utils/uvl_params.py +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli.egg-info/dependency_links.txt +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli.egg-info/entry_points.txt +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli.egg-info/requires.txt +0 -0
- {splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli.egg-info/top_level.txt +0 -0
|
@@ -10,7 +10,7 @@ from splent_cli.utils.path_utils import PathUtils
|
|
|
10
10
|
# Segments separated by ':', each starting with a letter. Dashes are allowed
|
|
11
11
|
# in the Click name (feature:inject-config) and become '_' in the file name
|
|
12
12
|
# and the Python identifier.
|
|
13
|
-
_NAME_RE = re.compile(r"[a-z][a-z0-9_-]*(:[a-z][a-z0-9_-]*)
|
|
13
|
+
_NAME_RE = re.compile(r"[a-z][a-z0-9_-]*(:[a-z][a-z0-9_-]*)?")
|
|
14
14
|
|
|
15
15
|
# Names the generated module already uses; a command function with one of
|
|
16
16
|
# these names would shadow the import it relies on.
|
|
@@ -33,7 +33,7 @@ def _validate_name(name: str) -> tuple[str, str]:
|
|
|
33
33
|
):
|
|
34
34
|
raise click.ClickException(
|
|
35
35
|
f"Invalid command name '{name}'. Use lowercase letters, digits, "
|
|
36
|
-
"'_' and '-', starting with a letter,
|
|
36
|
+
"'_' and '-', starting with a letter, and at most one ':' "
|
|
37
37
|
"(for example db:dump-all). Python keywords and the names click, "
|
|
38
38
|
"current_app and requires_app are not allowed."
|
|
39
39
|
)
|
{splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_frontend_init.py
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""
|
|
2
|
-
splent feature:frontend
|
|
2
|
+
splent feature:frontend-init
|
|
3
3
|
|
|
4
4
|
Move a feature to frontend/ (SD-01): its bundle is then built by the SPLENT
|
|
5
5
|
toolchain from frontend/package.json, against the feature's own
|
|
@@ -17,6 +17,7 @@ from splent_cli.services import frontend
|
|
|
17
17
|
from splent_cli.commands.feature.feature_npm import editable_frontend_root
|
|
18
18
|
from splent_cli.utils.io_utils import load_toml
|
|
19
19
|
from splent_cli.utils.template_drift import feature_ctx, render_template
|
|
20
|
+
from splent_cli.utils.command_loader import old_name
|
|
20
21
|
|
|
21
22
|
# The SPLENT-owned files of a feature with frontend/, written as
|
|
22
23
|
# feature:sync-template would write them.
|
|
@@ -176,7 +177,7 @@ def _leftovers(
|
|
|
176
177
|
|
|
177
178
|
|
|
178
179
|
@click.command(
|
|
179
|
-
"feature:frontend
|
|
180
|
+
"feature:frontend-init",
|
|
180
181
|
short_help="Give a feature a frontend/ of its own, built by the SPLENT toolchain.",
|
|
181
182
|
)
|
|
182
183
|
@click.argument("feature_ref")
|
|
@@ -208,8 +209,8 @@ def feature_frontend_init(feature_ref, adopt_vendor):
|
|
|
208
209
|
|
|
209
210
|
\b
|
|
210
211
|
Examples:
|
|
211
|
-
splent feature:frontend
|
|
212
|
-
splent feature:frontend
|
|
212
|
+
splent feature:frontend-init charts
|
|
213
|
+
splent feature:frontend-init charts --adopt-vendor
|
|
213
214
|
"""
|
|
214
215
|
root, name = editable_frontend_root(feature_ref)
|
|
215
216
|
if frontend.declares(root):
|
|
@@ -247,7 +248,7 @@ def feature_frontend_init(feature_ref, adopt_vendor):
|
|
|
247
248
|
if fallback:
|
|
248
249
|
(root / "frontend" / "webpack.extra.js").write_text(
|
|
249
250
|
"// What the feature's webpack.config.js set beyond the SPLENT preset,\n"
|
|
250
|
-
"// merged over it (feature:frontend
|
|
251
|
+
"// merged over it (feature:frontend-init carried it over).\n"
|
|
251
252
|
"module.exports = {\n"
|
|
252
253
|
f" resolve: {{ fallback: {json.dumps(fallback)} }},\n"
|
|
253
254
|
"};\n",
|
|
@@ -308,4 +309,7 @@ def feature_frontend_init(feature_ref, adopt_vendor):
|
|
|
308
309
|
click.echo()
|
|
309
310
|
|
|
310
311
|
|
|
311
|
-
|
|
312
|
+
cli_commands = [
|
|
313
|
+
feature_frontend_init,
|
|
314
|
+
old_name("feature:frontend:init", feature_frontend_init),
|
|
315
|
+
]
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""
|
|
2
|
-
splent feature:hook
|
|
2
|
+
splent feature:hook-add
|
|
3
3
|
|
|
4
4
|
Add a new template hook registration to a feature's hooks.py.
|
|
5
5
|
Also updates [tool.splent.contract.provides].hooks in pyproject.toml.
|
|
@@ -17,13 +17,14 @@ from pathlib import Path
|
|
|
17
17
|
from splent_cli.services import context
|
|
18
18
|
from splent_cli.utils.feature_utils import normalize_namespace
|
|
19
19
|
from splent_cli.utils.io_utils import atomic_write
|
|
20
|
+
from splent_cli.utils.command_loader import old_name
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
DEFAULT_NAMESPACE = os.getenv("SPLENT_DEFAULT_NAMESPACE", "splent_io")
|
|
23
24
|
|
|
24
25
|
|
|
25
26
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
26
|
-
# Helpers (shared with feature:hook
|
|
27
|
+
# Helpers (shared with feature:hook-remove)
|
|
27
28
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
28
29
|
|
|
29
30
|
|
|
@@ -317,7 +318,7 @@ def _check_function_name(function_name: str) -> None:
|
|
|
317
318
|
|
|
318
319
|
|
|
319
320
|
@click.command(
|
|
320
|
-
"feature:hook
|
|
321
|
+
"feature:hook-add",
|
|
321
322
|
short_help="Add a new template hook to a feature's hooks.py.",
|
|
322
323
|
)
|
|
323
324
|
@click.argument("feature_ref")
|
|
@@ -342,14 +343,14 @@ def feature_hook_add(feature_ref, slot, function_name):
|
|
|
342
343
|
|
|
343
344
|
\b
|
|
344
345
|
Example:
|
|
345
|
-
splent feature:hook
|
|
346
|
+
splent feature:hook-add splent_feature_notes layout.sidebar render_notes_sidebar
|
|
346
347
|
"""
|
|
347
348
|
_check_slot(slot)
|
|
348
349
|
_check_function_name(function_name)
|
|
349
350
|
|
|
350
351
|
workspace = str(context.workspace())
|
|
351
352
|
feature_path, ns, name = resolve_editable(
|
|
352
|
-
feature_ref, workspace, "feature:hook
|
|
353
|
+
feature_ref, workspace, "feature:hook-add"
|
|
353
354
|
)
|
|
354
355
|
|
|
355
356
|
package_dir = feature_path / "src" / ns / name
|
|
@@ -403,4 +404,4 @@ def feature_hook_add(feature_ref, slot, function_name):
|
|
|
403
404
|
click.echo()
|
|
404
405
|
|
|
405
406
|
|
|
406
|
-
|
|
407
|
+
cli_commands = [feature_hook_add, old_name("feature:hook:add", feature_hook_add)]
|
{splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/feature/feature_hook_remove.py
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""
|
|
2
|
-
splent feature:hook
|
|
2
|
+
splent feature:hook-remove
|
|
3
3
|
|
|
4
4
|
Remove a template hook registration from a feature's hooks.py.
|
|
5
5
|
Optionally also removes the callback function definition.
|
|
@@ -17,6 +17,7 @@ from splent_cli.commands.feature.feature_hook_add import (
|
|
|
17
17
|
rewrite_provides_hooks,
|
|
18
18
|
)
|
|
19
19
|
from splent_cli.utils.io_utils import atomic_write
|
|
20
|
+
from splent_cli.utils.command_loader import old_name
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -90,7 +91,7 @@ def _remove_trailing_blank_lines(text: str) -> str:
|
|
|
90
91
|
|
|
91
92
|
|
|
92
93
|
@click.command(
|
|
93
|
-
"feature:hook
|
|
94
|
+
"feature:hook-remove",
|
|
94
95
|
short_help="Remove a template hook from a feature's hooks.py.",
|
|
95
96
|
)
|
|
96
97
|
@click.argument("feature_ref")
|
|
@@ -116,12 +117,12 @@ def feature_hook_remove(feature_ref, slot, with_function, yes):
|
|
|
116
117
|
|
|
117
118
|
\b
|
|
118
119
|
Example:
|
|
119
|
-
splent feature:hook
|
|
120
|
-
splent feature:hook
|
|
120
|
+
splent feature:hook-remove splent_feature_notes layout.sidebar
|
|
121
|
+
splent feature:hook-remove splent_feature_notes layout.sidebar --with-function -y
|
|
121
122
|
"""
|
|
122
123
|
workspace = str(context.workspace())
|
|
123
124
|
feature_path, ns, name = resolve_editable(
|
|
124
|
-
feature_ref, workspace, "feature:hook
|
|
125
|
+
feature_ref, workspace, "feature:hook-remove"
|
|
125
126
|
)
|
|
126
127
|
|
|
127
128
|
hooks_path = feature_path / "src" / ns / name / "hooks.py"
|
|
@@ -185,4 +186,7 @@ def feature_hook_remove(feature_ref, slot, with_function, yes):
|
|
|
185
186
|
click.echo()
|
|
186
187
|
|
|
187
188
|
|
|
188
|
-
|
|
189
|
+
cli_commands = [
|
|
190
|
+
feature_hook_remove,
|
|
191
|
+
old_name("feature:hook:remove", feature_hook_remove),
|
|
192
|
+
]
|
|
@@ -138,7 +138,7 @@ def feature_hooks(feature_ref, as_json):
|
|
|
138
138
|
click.echo()
|
|
139
139
|
click.echo(
|
|
140
140
|
click.style(" Manage hooks with:", fg="bright_black")
|
|
141
|
-
+ f" splent feature:hook
|
|
141
|
+
+ f" splent feature:hook-add {name} <slot> <function>"
|
|
142
142
|
)
|
|
143
143
|
click.echo()
|
|
144
144
|
|
|
@@ -68,7 +68,7 @@ def feature_npm(feature_ref, npm_args):
|
|
|
68
68
|
if not frontend.declares(root):
|
|
69
69
|
raise click.ClickException(
|
|
70
70
|
f"{name} has no frontend/package.json. Create it with "
|
|
71
|
-
f"splent feature:frontend
|
|
71
|
+
f"splent feature:frontend-init {name}."
|
|
72
72
|
)
|
|
73
73
|
args = [*npm_args, "--ignore-scripts"]
|
|
74
74
|
if npm_args[0] in _SAVING:
|
|
@@ -80,7 +80,7 @@ def product_commands():
|
|
|
80
80
|
own = _own_commands()
|
|
81
81
|
product = context.active_app() or "product"
|
|
82
82
|
|
|
83
|
-
if not registry
|
|
83
|
+
if not (registry or own.commands or own.shadowed or own.refused or own.error):
|
|
84
84
|
click.echo()
|
|
85
85
|
click.secho(" No feature or product commands registered.", fg="yellow")
|
|
86
86
|
click.echo()
|
|
@@ -108,6 +108,12 @@ def product_commands():
|
|
|
108
108
|
_table("Product Commands", "Product", own_rows)
|
|
109
109
|
click.echo()
|
|
110
110
|
click.secho(f" {len(own_rows)} command(s) of {product}'s own.", dim=True)
|
|
111
|
+
for name in own.refused:
|
|
112
|
+
click.secho(
|
|
113
|
+
f" ⚠ {product} has a command {name}, which cannot be reached: a "
|
|
114
|
+
"command's name has one colon. Use a hyphen.",
|
|
115
|
+
fg="yellow",
|
|
116
|
+
)
|
|
111
117
|
for name in own.shadowed:
|
|
112
118
|
click.secho(
|
|
113
119
|
f" ⚠ {product} has a command {name}, which is the CLI's own and "
|
{splent_cli-1.52.0 → splent_cli-1.54.0}/src/splent_cli/commands/product/product_frontend_audit.py
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""
|
|
2
|
-
product:frontend
|
|
2
|
+
product:frontend-audit — what the product's bundles ship, audited as one set.
|
|
3
3
|
|
|
4
4
|
Each feature with frontend/ audits its own lock when it is released (npm
|
|
5
5
|
audit, services/frontend.py), but a bundle is immutable: an advisory
|
|
@@ -28,6 +28,7 @@ import click
|
|
|
28
28
|
from splent_cli.services import compose, context, frontend
|
|
29
29
|
from splent_cli.utils.frontend_check import LOCK_FILE, read_lock
|
|
30
30
|
from splent_cli.utils.npm_semver import satisfies
|
|
31
|
+
from splent_cli.utils.command_loader import old_name
|
|
31
32
|
|
|
32
33
|
DEFAULT_REGISTRY = "https://registry.npmjs.org"
|
|
33
34
|
ADVISORIES = "/-/npm/v1/security/advisories/bulk"
|
|
@@ -206,7 +207,7 @@ def _vendored(workspace: str, feature: dict, name: str) -> list[dict]:
|
|
|
206
207
|
|
|
207
208
|
|
|
208
209
|
@click.command(
|
|
209
|
-
"product:frontend
|
|
210
|
+
"product:frontend-audit",
|
|
210
211
|
short_help="Audit what the product's bundles ship against npm's advisories.",
|
|
211
212
|
)
|
|
212
213
|
@click.option(
|
|
@@ -234,8 +235,8 @@ def product_frontend_audit(sbom_path):
|
|
|
234
235
|
|
|
235
236
|
\b
|
|
236
237
|
Examples:
|
|
237
|
-
splent product:frontend
|
|
238
|
-
splent product:frontend
|
|
238
|
+
splent product:frontend-audit
|
|
239
|
+
splent product:frontend-audit --sbom frontend.sbom.cdx.json
|
|
239
240
|
"""
|
|
240
241
|
product = context.require_app()
|
|
241
242
|
workspace = str(context.workspace())
|
|
@@ -320,4 +321,7 @@ def _product_version(product_dir: str) -> str:
|
|
|
320
321
|
return str(data.get("project", {}).get("version") or "unknown")
|
|
321
322
|
|
|
322
323
|
|
|
323
|
-
|
|
324
|
+
cli_commands = [
|
|
325
|
+
product_frontend_audit,
|
|
326
|
+
old_name("product:frontend:audit", product_frontend_audit),
|
|
327
|
+
]
|
|
@@ -27,7 +27,7 @@ from pathlib import Path
|
|
|
27
27
|
|
|
28
28
|
import click
|
|
29
29
|
|
|
30
|
-
from splent_cli.services import context, web_container
|
|
30
|
+
from splent_cli.services import context, ui_audit, web_container
|
|
31
31
|
from splent_cli.utils.feature_utils import (
|
|
32
32
|
load_product_features,
|
|
33
33
|
load_product_pyproject,
|
|
@@ -131,30 +131,34 @@ def _run_product_tests(product, workspace, levels, verbose):
|
|
|
131
131
|
|
|
132
132
|
rc = run(cmd, check=False, env=env_vars).returncode
|
|
133
133
|
|
|
134
|
-
if not own:
|
|
135
|
-
return rc
|
|
136
|
-
|
|
137
134
|
if levels:
|
|
138
135
|
# A level flag asks for a quick, partial run. The product's tests
|
|
139
136
|
# build its whole app and are not split by level, so they wait for
|
|
140
137
|
# a full run, which is the one the release checks and the CI make.
|
|
138
|
+
if own:
|
|
139
|
+
click.secho(
|
|
140
|
+
f"\n {product}'s own tests ({OWN_TESTS_DIR}/) run only without a "
|
|
141
|
+
"level flag.",
|
|
142
|
+
dim=True,
|
|
143
|
+
)
|
|
144
|
+
return rc
|
|
145
|
+
|
|
146
|
+
if own:
|
|
141
147
|
click.secho(
|
|
142
|
-
f"\n {product}
|
|
143
|
-
"
|
|
144
|
-
|
|
148
|
+
f"\n ▶ {product} its own tests ({len(own)} file(s) in {OWN_TESTS_DIR}/)",
|
|
149
|
+
fg="cyan",
|
|
150
|
+
bold=True,
|
|
145
151
|
)
|
|
146
|
-
|
|
152
|
+
cmd = [sys.executable, "-m", "splent_cli", "product:test", "--own-tests"]
|
|
153
|
+
if verbose:
|
|
154
|
+
cmd.append("-v")
|
|
155
|
+
rc = run(cmd, check=False, env=env_vars).returncode or rc
|
|
147
156
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
cmd = [sys.executable, "-m", "splent_cli", "product:test", "--own-tests"]
|
|
154
|
-
if verbose:
|
|
155
|
-
cmd.append("-v")
|
|
156
|
-
own_rc = run(cmd, check=False, env=env_vars).returncode
|
|
157
|
-
return rc or own_rc
|
|
157
|
+
# The look of its pages, when the product asks for it and its stack is up.
|
|
158
|
+
if ui_audit.declared(product_path):
|
|
159
|
+
cmd = [sys.executable, "-m", "splent_cli", "product:ui-audit", "--if-up"]
|
|
160
|
+
rc = run(cmd, check=False, env=env_vars).returncode or rc
|
|
161
|
+
return rc
|
|
158
162
|
|
|
159
163
|
|
|
160
164
|
def _run_own_tests(product, verbose) -> None:
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
"""
|
|
2
|
+
product:ui-audit — look at every page of the product in a real browser.
|
|
3
|
+
|
|
4
|
+
The checks live in services/ui_audit.py and the page itself, in
|
|
5
|
+
templates/ui_audit/measure.js. This is what runs them: in the product's web
|
|
6
|
+
container, the one place its Selenium grid can be reached from.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import os
|
|
10
|
+
import shutil
|
|
11
|
+
|
|
12
|
+
import click
|
|
13
|
+
|
|
14
|
+
from splent_cli.services import context, ui_audit, web_container
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class _CannotRun(Exception):
|
|
18
|
+
"""No browser or no app to look at, which says nothing about the pages."""
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _delegated_args(
|
|
22
|
+
url, start, widths, themes, public_only, screenshots, max_pages, if_up
|
|
23
|
+
):
|
|
24
|
+
args = ["product:ui-audit"]
|
|
25
|
+
if if_up:
|
|
26
|
+
args.append("--if-up")
|
|
27
|
+
if url:
|
|
28
|
+
args += ["--url", url]
|
|
29
|
+
for path in start:
|
|
30
|
+
args += ["--start", path]
|
|
31
|
+
for width in widths:
|
|
32
|
+
args += ["--width", str(width)]
|
|
33
|
+
if len(themes) == 1:
|
|
34
|
+
args += ["--theme", themes[0]]
|
|
35
|
+
if public_only:
|
|
36
|
+
args.append("--public-only")
|
|
37
|
+
if screenshots:
|
|
38
|
+
args.append("--screenshots")
|
|
39
|
+
if max_pages != ui_audit.MAX_PAGES:
|
|
40
|
+
args += ["--max-pages", str(max_pages)]
|
|
41
|
+
return args
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def render(results, out) -> int:
|
|
45
|
+
"""Print what RESULTS found. Returns how many distinct problems."""
|
|
46
|
+
summary = ui_audit.summarize(results)
|
|
47
|
+
problems = 0
|
|
48
|
+
for kind, title in ui_audit.KINDS.items():
|
|
49
|
+
entries = summary.get(kind)
|
|
50
|
+
if not entries:
|
|
51
|
+
continue
|
|
52
|
+
problems += len(entries)
|
|
53
|
+
click.echo()
|
|
54
|
+
click.secho(f" {title} ({len(entries)})", bold=True)
|
|
55
|
+
ranked = sorted(entries.items(), key=lambda kv: -len(kv[1]["paths"]))
|
|
56
|
+
for key, entry in ranked:
|
|
57
|
+
click.echo(f" {key}")
|
|
58
|
+
pages = len(entry["paths"])
|
|
59
|
+
more = f" and {pages - 1} more" if pages > 1 else ""
|
|
60
|
+
detail = f" {entry['detail']}" if entry["detail"] else ""
|
|
61
|
+
click.secho(
|
|
62
|
+
f" [{ui_audit.where_label(entry['where'])}] "
|
|
63
|
+
f"{entry['paths'][0]}{more}{detail}",
|
|
64
|
+
dim=True,
|
|
65
|
+
)
|
|
66
|
+
failed = ui_audit.errors_of(results)
|
|
67
|
+
for record in failed[:5]:
|
|
68
|
+
click.secho(
|
|
69
|
+
f" could not measure {record['url']}: {record['error']}", fg="yellow"
|
|
70
|
+
)
|
|
71
|
+
click.echo()
|
|
72
|
+
pages = {(r.get("who"), r.get("path")) for r in results if "error" not in r}
|
|
73
|
+
click.echo(f" {len(pages)} pages measured, {len(results)} measurements.")
|
|
74
|
+
click.secho(f" Report and screenshots in {out}", dim=True)
|
|
75
|
+
return problems + len(failed)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@click.command(
|
|
79
|
+
"product:ui-audit",
|
|
80
|
+
short_help="Look at every page in a real browser, at every width and theme.",
|
|
81
|
+
)
|
|
82
|
+
@click.option(
|
|
83
|
+
"--url",
|
|
84
|
+
default=None,
|
|
85
|
+
help="Audit this address, such as your production site, as an anonymous "
|
|
86
|
+
"visitor. Defaults to the product's development app.",
|
|
87
|
+
)
|
|
88
|
+
@click.option("--start", multiple=True, help="Start from this path. Can be repeated.")
|
|
89
|
+
@click.option(
|
|
90
|
+
"--width",
|
|
91
|
+
"widths",
|
|
92
|
+
multiple=True,
|
|
93
|
+
type=int,
|
|
94
|
+
help="Only this width, in both themes. Can be repeated.",
|
|
95
|
+
)
|
|
96
|
+
@click.option(
|
|
97
|
+
"--theme",
|
|
98
|
+
type=click.Choice(["light", "dark", "both"]),
|
|
99
|
+
default="both",
|
|
100
|
+
help="Which theme to look at.",
|
|
101
|
+
)
|
|
102
|
+
@click.option("--public-only", is_flag=True, help="Skip the pages behind a login.")
|
|
103
|
+
@click.option(
|
|
104
|
+
"--screenshots",
|
|
105
|
+
is_flag=True,
|
|
106
|
+
help="Keep a screenshot of every page, not only of those with a problem.",
|
|
107
|
+
)
|
|
108
|
+
@click.option(
|
|
109
|
+
"--max-pages",
|
|
110
|
+
default=ui_audit.MAX_PAGES,
|
|
111
|
+
show_default=True,
|
|
112
|
+
help="Stop discovering pages after this many, per visitor.",
|
|
113
|
+
)
|
|
114
|
+
@click.option(
|
|
115
|
+
"--if-up",
|
|
116
|
+
is_flag=True,
|
|
117
|
+
hidden=True,
|
|
118
|
+
help="Pass, saying so, when there is no grid or no app to look at "
|
|
119
|
+
"(used by product:test, whose tests need neither).",
|
|
120
|
+
)
|
|
121
|
+
def product_ui_audit(
|
|
122
|
+
url, start, widths, theme, public_only, screenshots, max_pages, if_up
|
|
123
|
+
):
|
|
124
|
+
"""
|
|
125
|
+
Look at every page of the product in a real browser.
|
|
126
|
+
|
|
127
|
+
\b
|
|
128
|
+
Walks the links from the first page and, in Chrome, at five widths from
|
|
129
|
+
a wide screen to a small phone and in the light and dark themes, looks
|
|
130
|
+
for what the tests cannot see: what leaves the screen, is cut off, is
|
|
131
|
+
squeezed or sits under something else, text too faint to read, light
|
|
132
|
+
boxes left on a dark page, and pictures that fail or fade away.
|
|
133
|
+
|
|
134
|
+
\b
|
|
135
|
+
Fails when it finds anything, so it can stop a release. product:test
|
|
136
|
+
runs it too when the product has a [tool.splent.ui_audit] table.
|
|
137
|
+
|
|
138
|
+
\b
|
|
139
|
+
Examples:
|
|
140
|
+
splent product:ui-audit
|
|
141
|
+
splent product:ui-audit --width 390 --theme dark
|
|
142
|
+
splent product:ui-audit --url https://www.example.org --screenshots
|
|
143
|
+
"""
|
|
144
|
+
product = context.require_app()
|
|
145
|
+
themes = ("light", "dark") if theme == "both" else (theme,)
|
|
146
|
+
try:
|
|
147
|
+
if not web_container.is_product_container():
|
|
148
|
+
container = web_container.name(product)
|
|
149
|
+
if not web_container.running(container):
|
|
150
|
+
raise _CannotRun(
|
|
151
|
+
f"{container} is not running. Start the product with "
|
|
152
|
+
"splent product:up, then splent product:run --dev"
|
|
153
|
+
)
|
|
154
|
+
raise SystemExit(
|
|
155
|
+
web_container.delegate(
|
|
156
|
+
product,
|
|
157
|
+
_delegated_args(
|
|
158
|
+
url,
|
|
159
|
+
start,
|
|
160
|
+
widths,
|
|
161
|
+
themes,
|
|
162
|
+
public_only,
|
|
163
|
+
screenshots,
|
|
164
|
+
max_pages,
|
|
165
|
+
if_up,
|
|
166
|
+
),
|
|
167
|
+
)
|
|
168
|
+
)
|
|
169
|
+
audit, out = _audit_the_product(
|
|
170
|
+
product, url, start, widths, themes, public_only, screenshots, max_pages
|
|
171
|
+
)
|
|
172
|
+
except _CannotRun as error:
|
|
173
|
+
if not if_up:
|
|
174
|
+
raise click.ClickException(str(error)) from error
|
|
175
|
+
click.secho(f"\n The UI audit did not run. {error}", fg="yellow")
|
|
176
|
+
return
|
|
177
|
+
except ui_audit.AuditError as error:
|
|
178
|
+
raise click.ClickException(str(error)) from error
|
|
179
|
+
|
|
180
|
+
if render(audit.results, out):
|
|
181
|
+
click.secho(" The audit found problems.\n", fg="red")
|
|
182
|
+
raise SystemExit(1)
|
|
183
|
+
click.secho(" Nothing wrong.\n", fg="green")
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def _audit_the_product(
|
|
187
|
+
product, url, start, widths, themes, public_only, screenshots, max_pages
|
|
188
|
+
):
|
|
189
|
+
"""Run the audit here, in the web container. Returns it and where it wrote."""
|
|
190
|
+
workspace = context.workspace()
|
|
191
|
+
config = ui_audit.read_config(workspace / product)
|
|
192
|
+
if start:
|
|
193
|
+
config.start = list(start)
|
|
194
|
+
|
|
195
|
+
grid_url = os.getenv("SELENIUM_GRID_URL")
|
|
196
|
+
grid = ui_audit.Grid(grid_url) if grid_url else None
|
|
197
|
+
if grid is None or not grid.ready():
|
|
198
|
+
raise _CannotRun(
|
|
199
|
+
"No Selenium grid answers here. It is part of the product's development "
|
|
200
|
+
"stack: start it with splent product:up"
|
|
201
|
+
)
|
|
202
|
+
base = url or os.getenv("SELENIUM_TARGET_URL")
|
|
203
|
+
if not base:
|
|
204
|
+
raise _CannotRun(
|
|
205
|
+
"SELENIUM_TARGET_URL is not set, so the browser does not know where the "
|
|
206
|
+
"app is. Pass --url"
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
out = workspace / ".splent_cache" / "ui_audit" / product
|
|
210
|
+
shutil.rmtree(out, ignore_errors=True)
|
|
211
|
+
audit = ui_audit.Audit(
|
|
212
|
+
grid,
|
|
213
|
+
base,
|
|
214
|
+
config,
|
|
215
|
+
out=out,
|
|
216
|
+
max_pages=max_pages,
|
|
217
|
+
log=lambda line: click.echo(line),
|
|
218
|
+
)
|
|
219
|
+
audit.every_screenshot = screenshots
|
|
220
|
+
runs = ui_audit.plan(widths, themes)
|
|
221
|
+
|
|
222
|
+
click.secho(f"\n Auditing {base}\n", bold=True)
|
|
223
|
+
try:
|
|
224
|
+
audit.measure_as("public", None, runs)
|
|
225
|
+
# A login is a test account of the development app, and only there.
|
|
226
|
+
if not url and not public_only:
|
|
227
|
+
for login in config.logins:
|
|
228
|
+
audit.measure_as(login.split(":", 1)[0].split("@")[0], login, runs)
|
|
229
|
+
except ui_audit.NothingAnswers as error:
|
|
230
|
+
raise _CannotRun(str(error)) from error
|
|
231
|
+
finally:
|
|
232
|
+
audit.write_report()
|
|
233
|
+
return audit, out
|
|
@@ -9,7 +9,9 @@ context.
|
|
|
9
9
|
|
|
10
10
|
The CLI's own ``product:*`` commands win. A product command named like one
|
|
11
11
|
of them cannot be reached, and product:commands says so: a CLI that ships a
|
|
12
|
-
new built-in never takes a product's command away unnoticed.
|
|
12
|
+
new built-in never takes a product's command away unnoticed. A name with a
|
|
13
|
+
colon of its own would make two, which no command has, so it is left out and
|
|
14
|
+
product:commands says so too.
|
|
13
15
|
"""
|
|
14
16
|
|
|
15
17
|
from __future__ import annotations
|
|
@@ -25,12 +27,14 @@ MODULE = "commands"
|
|
|
25
27
|
|
|
26
28
|
class OwnCommands(NamedTuple):
|
|
27
29
|
"""What a product contributes: ``commands`` by the name they are run
|
|
28
|
-
with, ``shadowed`` the names a built-in took,
|
|
29
|
-
|
|
30
|
+
with, ``shadowed`` the names a built-in took, ``error`` why its commands
|
|
31
|
+
module could not be imported, None when it could, and ``refused`` the
|
|
32
|
+
names with a colon of their own."""
|
|
30
33
|
|
|
31
34
|
commands: dict[str, click.Command]
|
|
32
35
|
shadowed: list[str]
|
|
33
36
|
error: str | None
|
|
37
|
+
refused: list[str] = []
|
|
34
38
|
|
|
35
39
|
|
|
36
40
|
NONE = OwnCommands({}, [], None)
|
|
@@ -62,15 +66,18 @@ def collect(product: str | None, builtin) -> OwnCommands:
|
|
|
62
66
|
commands = declared(product)
|
|
63
67
|
except Exception as e:
|
|
64
68
|
return OwnCommands({}, [], f"{product}.{MODULE}: {e}")
|
|
65
|
-
found, shadowed = {}, []
|
|
69
|
+
found, shadowed, refused = {}, [], []
|
|
66
70
|
for command in commands:
|
|
67
71
|
if not command.name:
|
|
68
72
|
continue
|
|
69
73
|
name = PREFIX + command.name
|
|
74
|
+
if ":" in command.name:
|
|
75
|
+
refused.append(name)
|
|
76
|
+
continue
|
|
70
77
|
if name in builtin:
|
|
71
78
|
shadowed.append(name)
|
|
72
79
|
continue
|
|
73
80
|
# Run in the app's context, as a feature's (cli.py).
|
|
74
81
|
command.requires_app = True # type: ignore[attr-defined]
|
|
75
82
|
found[name] = command
|
|
76
|
-
return OwnCommands(found, shadowed, None)
|
|
83
|
+
return OwnCommands(found, shadowed, None, refused)
|