splent-cli 1.53.0__tar.gz → 1.55.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.53.0/src/splent_cli.egg-info → splent_cli-1.55.0}/PKG-INFO +1 -1
- {splent_cli-1.53.0 → splent_cli-1.55.0}/pyproject.toml +1 -1
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/command/command_create.py +2 -2
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_frontend_init.py +10 -6
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_hook_add.py +7 -6
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_hook_remove.py +10 -6
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_hooks.py +1 -1
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_npm.py +1 -1
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_pip_install.py +198 -3
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/product/product_commands.py +7 -1
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/product/product_frontend_audit.py +9 -5
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/product/product_test.py +22 -18
- splent_cli-1.55.0/src/splent_cli/commands/product/product_ui_audit.py +233 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/services/own_commands.py +12 -5
- splent_cli-1.55.0/src/splent_cli/services/ui_audit.py +483 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_Dockerfile.prod.j2 +108 -45
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_ci_validate.yml.j2 +1 -1
- splent_cli-1.55.0/src/splent_cli/templates/ui_audit/measure.js +226 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/toolchain/frontend/splent/legacy.js +1 -1
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/command_loader.py +10 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/frontend_check.py +1 -1
- {splent_cli-1.53.0 → splent_cli-1.55.0/src/splent_cli.egg-info}/PKG-INFO +1 -1
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli.egg-info/SOURCES.txt +3 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/COPYING +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/COPYING.LESSER +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/README.md +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/setup.cfg +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/__init__.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/__main__.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/cli.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/__init__.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/cache/__init__.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/cache/cache_clear.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/cache/cache_orphans.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/cache/cache_outdated.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/cache/cache_prune.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/cache/cache_size.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/cache/cache_status.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/cache/cache_usage.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/cache/cache_versions.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/check/__init__.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/check/check_contracts.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/check/check_deps.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/check/check_docker.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/check/check_env.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/check/check_features.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/check/check_github.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/check/check_infra.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/check/check_product.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/check/check_pypi.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/check/check_pyproject.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/check/check_releases.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/check/check_vendor.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/clear/__init__.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/clear/clear_build.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/clear/clear_log.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/clear/clear_uploads.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/command/__init__.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/coverage.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/database/db_console.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/database/db_dump.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/database/db_migrate.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/database/db_reset.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/database/db_restore.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/database/db_rollback.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/database/db_seed.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/database/db_status.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/database/db_upgrade.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/doctor.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/env/env_list.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/env/env_set.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/env/env_show.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/export/__init__.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/export/export_puml.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_add.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_attach.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_clean.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_clone.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_compat.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_compile.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_contract.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_create.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_delete.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_detach.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_discard.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_drift.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_env.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_fork.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_git.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_impact.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_info.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_inject_config.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_install.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_list.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_order.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_outdated.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_pin.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_pull.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_refine.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_release.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_remove.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_rename.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_search.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_security.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_status.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_sync_template.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_test.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_translate.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_unlock.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_upgrade.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_versions.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_xray.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/lint.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/locust.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/marketplace/login.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/marketplace/logout.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/marketplace/marketplace_auth_utils.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/marketplace/marketplace_index.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/marketplace/whoami.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/product/__init__.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/product/product_auto_require.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/product/product_build.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/product/product_clean.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/product/product_config.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/product/product_configure.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/product/product_console.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/product/product_containers.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/product/product_create.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/product/product_deploy.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/product/product_derive.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/product/product_deselect.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/product/product_down.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/product/product_drift.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/product/product_env.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/product/product_list.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/product/product_logs.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/product/product_missing.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/product/product_params.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/product/product_port.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/product/product_release.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/product/product_resolve.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/product/product_restart.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/product/product_routes.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/product/product_run.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/product/product_select.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/product/product_shell.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/product/product_signals.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/product/product_sync_template.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/product/product_up.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/product/product_validate.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/release/__init__.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/release/release_core.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/release/release_resume.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/selenium.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/spl/__init__.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/spl/spl_add_constraints.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/spl/spl_add_feature.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/spl/spl_compare.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/spl/spl_configurations.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/spl/spl_create.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/spl/spl_deps.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/spl/spl_features.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/spl/spl_fetch.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/spl/spl_info.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/spl/spl_list.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/spl/spl_outdated.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/spl/spl_pin.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/spl/spl_publish.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/spl/spl_remove_feature.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/spl/spl_utils.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/storage/__init__.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/storage/storage_migrate.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/tokens_setup.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/uvl/uvl_utils.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/version.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/services/__init__.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/services/compose.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/services/context.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/services/credentials.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/services/deploy_bundle.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/services/editable_refresh.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/services/frontend.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/services/image_registry.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/services/index_refresh.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/services/marketplace.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/services/marketplace_api.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/services/marketplace_url.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/services/neutral_app.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/services/preflight.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/services/pypi_quota.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/services/registry.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/services/release.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/services/release_dry_run.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/services/release_gate.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/services/release_workspace.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/services/security_scan.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/services/source_mirror.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/services/spl_store.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/services/web_container.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_.gitignore.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_MANIFEST.in.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_README.md.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_commands.py.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_config.py.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_docker-compose.dev.yml.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_docker-compose.prod.yml.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_docker.env.example.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_forms.py.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_frontend.npmrc.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_frontend_scripts.js.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_hooks.py.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_init.py.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_init_config.py.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_init_light.py.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_init_service.py.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_migrations_alembic.ini.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_migrations_env.py.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_migrations_script.py.mako.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_models.py.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_pyproject.toml.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_pyproject_minimal.toml.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_repositories.py.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_routes.py.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_scripts.js.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_seeders.py.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_services.py.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_services_service.py.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_signals.py.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_templates_index.html.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_tests_conftest.py.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_tests_e2e.py.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_tests_functional.py.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_tests_integration.py.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_tests_locustfile.py.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_tests_unit.py.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/feature/feature_webpack.config.js.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/licenses/COPYING +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/licenses/COPYING.LESSER +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_.env.dev.example.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_.env.prod.example.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_.gitignore.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_00_core_requirements_dev.sh.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_00_install_features.sh.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_01_compile_assets.sh.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_02_0_db_wait_connection.sh.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_02_1_db_create_db_test.sh.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_02_2_db_create_splent_migrations.sh.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_03_initialize_migrations.sh.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_04_handle_migrations.sh.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_05_0_start_app_dev.sh.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_05_1_start_app_prod.sh.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_400.html +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_401.html +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_404.html +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_500.html +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_Dockerfile.dev.dockerignore.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_Dockerfile.dev.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_Dockerfile.prod.dockerignore.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_README.md.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_app.css +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_app.js +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_base_template.html +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_ci_upgrade.yml.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_config.py.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_docker-compose.dev.yml.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_docker-compose.prod.yml.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_dropzone.css +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_entrypoint.dev.sh.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_entrypoint.prod.sh.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_errors.py.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_favicon.svg +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_init.py.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_logging.py.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_own.css +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_package.json.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_pyproject.toml.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/templates/product/product_uvl.j2 +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/toolchain/Dockerfile.frontend +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/toolchain/frontend/package-lock.json +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/toolchain/frontend/package.json +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/toolchain/frontend/splent/build.js +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/toolchain/frontend/splent/lint.js +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/toolchain/frontend/splent/plugin.js +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/toolchain/frontend/splent/preset.js +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/toolchain/frontend/splent/singletons.json +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/__init__.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/archetype.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/cache_utils.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/ci_services.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/ci_workflow.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/contract_freshness.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/db_client.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/db_utils.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/decorators.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/deploy_freshness.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/dynamic_imports.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/feature_installer.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/feature_naming.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/feature_params.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/feature_requirements.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/feature_resolution.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/feature_utils.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/forge.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/frontend_licenses.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/git_url.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/integrity.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/io_utils.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/lifecycle.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/manifest.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/menu_keys.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/migration_lock.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/npm_semver.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/path_utils.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/proc.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/redact.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/refinement_facts.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/running_version.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/template_drift.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/toml_edit.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/upgrade_plan.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/uvl_diagnosis.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/utils/uvl_params.py +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli.egg-info/dependency_links.txt +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli.egg-info/entry_points.txt +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli.egg-info/requires.txt +0 -0
- {splent_cli-1.53.0 → splent_cli-1.55.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.53.0 → splent_cli-1.55.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.53.0 → splent_cli-1.55.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:
|
{splent_cli-1.53.0 → splent_cli-1.55.0}/src/splent_cli/commands/feature/feature_pip_install.py
RENAMED
|
@@ -15,6 +15,13 @@ and because a private feature may deliberately never be published there.
|
|
|
15
15
|
Without the fallback, one unpublished feature makes the whole product
|
|
16
16
|
unbuildable even though its code is tagged and reachable.
|
|
17
17
|
|
|
18
|
+
Everything is installed by one pip run. Which channel serves each feature is
|
|
19
|
+
settled first, asking PyPI and the forge for all of them at once, and a tag is
|
|
20
|
+
named by the commit it points at: pip keeps the wheel it builds from a commit
|
|
21
|
+
in its cache, and the next build takes it from there instead of cloning and
|
|
22
|
+
building the feature again. Only when that run fails are the features
|
|
23
|
+
installed one at a time, which says which one failed and why.
|
|
24
|
+
|
|
18
25
|
Three things about this are worth stating plainly rather than discovering:
|
|
19
26
|
|
|
20
27
|
* only [tool.splent].features is read. features_dev and features_prod are
|
|
@@ -39,7 +46,9 @@ Example:
|
|
|
39
46
|
"""
|
|
40
47
|
|
|
41
48
|
import os
|
|
49
|
+
import subprocess
|
|
42
50
|
import sys
|
|
51
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
43
52
|
|
|
44
53
|
import click
|
|
45
54
|
import tomllib
|
|
@@ -154,6 +163,180 @@ def _last_line(output: str) -> str:
|
|
|
154
163
|
return _redacted(lines[-1]) if lines else "no output"
|
|
155
164
|
|
|
156
165
|
|
|
166
|
+
# How many PyPI and forge questions are asked at once.
|
|
167
|
+
PROBE_WORKERS = 16
|
|
168
|
+
|
|
169
|
+
# Seconds one question to PyPI or one ``git ls-remote`` may take.
|
|
170
|
+
PROBE_TIMEOUT = 20
|
|
171
|
+
|
|
172
|
+
# What a failed pip run is summed up with, counted from its end.
|
|
173
|
+
TAIL_LINES = 15
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def _asks_pypi() -> bool:
|
|
177
|
+
"""Whether pip installs from PyPI, so PyPI is the one to ask.
|
|
178
|
+
|
|
179
|
+
A PIP_INDEX_URL that points elsewhere (a mirror, a private index) serves
|
|
180
|
+
what PyPI does not say, so nothing is asked and the features are
|
|
181
|
+
installed one at a time, each trying its index first.
|
|
182
|
+
"""
|
|
183
|
+
index = os.getenv("PIP_INDEX_URL", "").strip()
|
|
184
|
+
return not index or index.rstrip("/") in (
|
|
185
|
+
"https://pypi.org/simple",
|
|
186
|
+
"https://pypi.python.org/simple",
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def _pypi_serves(dist: str, version: str) -> bool | None:
|
|
191
|
+
"""Whether PyPI serves ``dist==version``, None when it could not be asked."""
|
|
192
|
+
import requests
|
|
193
|
+
|
|
194
|
+
url = f"https://pypi.org/pypi/{dist}/{version}/json"
|
|
195
|
+
for _attempt in range(2):
|
|
196
|
+
try:
|
|
197
|
+
response = requests.get(url, timeout=PROBE_TIMEOUT)
|
|
198
|
+
except requests.RequestException:
|
|
199
|
+
continue
|
|
200
|
+
if response.status_code == 200:
|
|
201
|
+
return True
|
|
202
|
+
if response.status_code == 404:
|
|
203
|
+
return False
|
|
204
|
+
return None
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def _tag_commit(namespace: str, name: str, ref: str) -> tuple[str, str, str] | None:
|
|
208
|
+
"""(real_url, display_url, commit) of the tag, from the first spelling of
|
|
209
|
+
the namespace that has it, or None.
|
|
210
|
+
|
|
211
|
+
Asked with ``git ls-remote``, so nothing is cloned. An annotated tag is
|
|
212
|
+
named by the commit it points at, not by the tag object.
|
|
213
|
+
"""
|
|
214
|
+
env = {
|
|
215
|
+
**os.environ,
|
|
216
|
+
**forge.git_auth_env(),
|
|
217
|
+
"GIT_TERMINAL_PROMPT": "0",
|
|
218
|
+
"LC_ALL": "C",
|
|
219
|
+
}
|
|
220
|
+
for spelling in namespace_spellings(namespace):
|
|
221
|
+
real, display = https_url(spelling, name)
|
|
222
|
+
try:
|
|
223
|
+
result = subprocess.run(
|
|
224
|
+
["git", "ls-remote", real, f"refs/tags/{ref}", f"refs/tags/{ref}^{{}}"],
|
|
225
|
+
capture_output=True,
|
|
226
|
+
text=True,
|
|
227
|
+
timeout=PROBE_TIMEOUT,
|
|
228
|
+
env=env,
|
|
229
|
+
)
|
|
230
|
+
except (OSError, subprocess.TimeoutExpired):
|
|
231
|
+
continue
|
|
232
|
+
if result.returncode != 0:
|
|
233
|
+
continue
|
|
234
|
+
refs = dict(
|
|
235
|
+
reversed(line.split("\t", 1))
|
|
236
|
+
for line in result.stdout.splitlines()
|
|
237
|
+
if "\t" in line
|
|
238
|
+
)
|
|
239
|
+
commit = refs.get(f"refs/tags/{ref}^{{}}") or refs.get(f"refs/tags/{ref}")
|
|
240
|
+
if commit:
|
|
241
|
+
return real, display, commit
|
|
242
|
+
return None
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
def _pip_install_many(specs: list[str]) -> tuple[bool, str]:
|
|
246
|
+
"""One pip run for every requirement in ``specs``.
|
|
247
|
+
|
|
248
|
+
What pip says is shown as it says it, redacted line by line, so a long
|
|
249
|
+
build is never silent. Returns whether it succeeded and its last lines.
|
|
250
|
+
"""
|
|
251
|
+
auth = forge.git_auth_env()
|
|
252
|
+
cmd = [sys.executable, "-m", "pip", "install", "--progress-bar", "off", *specs]
|
|
253
|
+
tail: list[str] = []
|
|
254
|
+
try:
|
|
255
|
+
process = subprocess.Popen(
|
|
256
|
+
cmd,
|
|
257
|
+
stdout=subprocess.PIPE,
|
|
258
|
+
stderr=subprocess.STDOUT,
|
|
259
|
+
text=True,
|
|
260
|
+
env={**os.environ, **auth} if auth else None,
|
|
261
|
+
)
|
|
262
|
+
except OSError as exc:
|
|
263
|
+
return False, str(exc)
|
|
264
|
+
assert process.stdout is not None
|
|
265
|
+
for line in process.stdout:
|
|
266
|
+
line = _redacted(line.rstrip("\n"))
|
|
267
|
+
click.echo(f" {line}")
|
|
268
|
+
tail = [*tail, line][-TAIL_LINES:]
|
|
269
|
+
return process.wait() == 0, "\n".join(tail)
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def _requirement(entry, data, pypi_only, asks_pypi):
|
|
273
|
+
"""What one pip run installs for ``entry``.
|
|
274
|
+
|
|
275
|
+
Returns (spec, display, from_git), or None when it cannot be settled
|
|
276
|
+
without trying (PyPI could not be asked, or its tag could not be found),
|
|
277
|
+
which leaves the entry to the one-at-a-time install.
|
|
278
|
+
"""
|
|
279
|
+
namespace, name, version, ref = _parse_feature_entry(entry)
|
|
280
|
+
dist = feature_distribution(data, name)
|
|
281
|
+
if not version:
|
|
282
|
+
return dist, dist, None
|
|
283
|
+
spec = f"{dist}=={version}"
|
|
284
|
+
if pypi_only:
|
|
285
|
+
return spec, spec, None
|
|
286
|
+
if not (ref and namespace):
|
|
287
|
+
return spec, spec, None
|
|
288
|
+
if not asks_pypi:
|
|
289
|
+
return None
|
|
290
|
+
served = _pypi_serves(dist, version)
|
|
291
|
+
if served is None:
|
|
292
|
+
return None
|
|
293
|
+
if served:
|
|
294
|
+
return spec, spec, None
|
|
295
|
+
found = _tag_commit(namespace, name, ref)
|
|
296
|
+
if found is None:
|
|
297
|
+
return None
|
|
298
|
+
real, display, commit = found
|
|
299
|
+
return (
|
|
300
|
+
f"{dist} @ git+{real}@{commit}",
|
|
301
|
+
f"git+{display}@{ref} ({commit[:12]})",
|
|
302
|
+
f"{name} {ref}",
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
def _install_together(features, data, pypi_only) -> list[str] | None:
|
|
307
|
+
"""Install every feature in one pip run.
|
|
308
|
+
|
|
309
|
+
Returns what came from a git tag, or None when the features have to be
|
|
310
|
+
installed one at a time: one of them could not be settled in advance, or
|
|
311
|
+
the run failed and the one-at-a-time install says which feature broke it.
|
|
312
|
+
"""
|
|
313
|
+
asks_pypi = _asks_pypi()
|
|
314
|
+
with ThreadPoolExecutor(max_workers=PROBE_WORKERS) as pool:
|
|
315
|
+
plan = list(
|
|
316
|
+
pool.map(
|
|
317
|
+
lambda entry: _requirement(entry, data, pypi_only, asks_pypi),
|
|
318
|
+
features,
|
|
319
|
+
)
|
|
320
|
+
)
|
|
321
|
+
if any(item is None for item in plan):
|
|
322
|
+
return None
|
|
323
|
+
|
|
324
|
+
for _spec, display, from_git in plan:
|
|
325
|
+
click.echo(f" {'git ' if from_git else 'pypi'} {display}")
|
|
326
|
+
click.echo()
|
|
327
|
+
ok, tail = _pip_install_many([spec for spec, _display, _git in plan])
|
|
328
|
+
click.echo()
|
|
329
|
+
if not ok:
|
|
330
|
+
click.secho(
|
|
331
|
+
" Installing them together failed. Installing them one at a time, "
|
|
332
|
+
"to say which one:",
|
|
333
|
+
fg="yellow",
|
|
334
|
+
)
|
|
335
|
+
click.echo()
|
|
336
|
+
return None
|
|
337
|
+
return [from_git for _spec, _display, from_git in plan if from_git]
|
|
338
|
+
|
|
339
|
+
|
|
157
340
|
@click.command(
|
|
158
341
|
"feature:pip-install",
|
|
159
342
|
short_help="Install the declared features from PyPI, or from their git tag.",
|
|
@@ -204,15 +387,22 @@ def feature_pip_install(pypi_only):
|
|
|
204
387
|
|
|
205
388
|
click.echo(f" Installing {len(features)} feature(s)...\n")
|
|
206
389
|
|
|
390
|
+
unpinned = [
|
|
391
|
+
_parse_feature_entry(entry)[1]
|
|
392
|
+
for entry in features
|
|
393
|
+
if not _parse_feature_entry(entry)[2]
|
|
394
|
+
]
|
|
395
|
+
together = _install_together(features, data, pypi_only)
|
|
396
|
+
if together is not None:
|
|
397
|
+
_summary(features, unpinned, together, [])
|
|
398
|
+
return
|
|
399
|
+
|
|
207
400
|
failed = []
|
|
208
|
-
unpinned = []
|
|
209
401
|
from_git = []
|
|
210
402
|
for entry in features:
|
|
211
403
|
namespace, name, version, ref = _parse_feature_entry(entry)
|
|
212
404
|
dist = feature_distribution(data, name)
|
|
213
405
|
spec = f"{dist}=={version}" if version else dist
|
|
214
|
-
if not version:
|
|
215
|
-
unpinned.append(name)
|
|
216
406
|
|
|
217
407
|
click.echo(f" installing {spec}")
|
|
218
408
|
|
|
@@ -250,6 +440,11 @@ def feature_pip_install(pypi_only):
|
|
|
250
440
|
)
|
|
251
441
|
failed.append(spec)
|
|
252
442
|
|
|
443
|
+
_summary(features, unpinned, from_git, failed)
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
def _summary(features, unpinned, from_git, failed) -> None:
|
|
447
|
+
"""What was installed from where, and what failed (which exits 1)."""
|
|
253
448
|
click.echo()
|
|
254
449
|
if unpinned:
|
|
255
450
|
click.secho(
|
|
@@ -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.53.0 → splent_cli-1.55.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:
|