mirror of
https://github.com/apache/superset.git
synced 2026-04-19 08:04:53 +00:00
chore: Adds non-interactive mode to superset-extensions init command (#36308)
This commit is contained in:
committed by
GitHub
parent
b12f5f8394
commit
db995ad5bf
@@ -404,19 +404,57 @@ def dev(ctx: click.Context) -> None:
|
||||
|
||||
|
||||
@app.command()
|
||||
def init() -> None:
|
||||
id_ = click.prompt("Extension ID (unique identifier, alphanumeric only)", type=str)
|
||||
@click.option(
|
||||
"--id",
|
||||
"id_opt",
|
||||
default=None,
|
||||
help="Extension ID (alphanumeric and underscores only)",
|
||||
)
|
||||
@click.option("--name", "name_opt", default=None, help="Extension display name")
|
||||
@click.option(
|
||||
"--version", "version_opt", default=None, help="Initial version (default: 0.1.0)"
|
||||
)
|
||||
@click.option(
|
||||
"--license", "license_opt", default=None, help="License (default: Apache-2.0)"
|
||||
)
|
||||
@click.option(
|
||||
"--frontend/--no-frontend", "frontend_opt", default=None, help="Include frontend"
|
||||
)
|
||||
@click.option(
|
||||
"--backend/--no-backend", "backend_opt", default=None, help="Include backend"
|
||||
)
|
||||
def init(
|
||||
id_opt: str | None,
|
||||
name_opt: str | None,
|
||||
version_opt: str | None,
|
||||
license_opt: str | None,
|
||||
frontend_opt: bool | None,
|
||||
backend_opt: bool | None,
|
||||
) -> None:
|
||||
id_ = id_opt or click.prompt(
|
||||
"Extension ID (unique identifier, alphanumeric only)", type=str
|
||||
)
|
||||
if not re.match(r"^[a-zA-Z0-9_]+$", id_):
|
||||
click.secho(
|
||||
"❌ ID must be alphanumeric (letters, digits, underscore).", fg="red"
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
name = click.prompt("Extension name (human-readable display name)", type=str)
|
||||
version = click.prompt("Initial version", default="0.1.0")
|
||||
license = click.prompt("License", default="Apache-2.0")
|
||||
include_frontend = click.confirm("Include frontend?", default=True)
|
||||
include_backend = click.confirm("Include backend?", default=True)
|
||||
name = name_opt or click.prompt(
|
||||
"Extension name (human-readable display name)", type=str
|
||||
)
|
||||
version = version_opt or click.prompt("Initial version", default="0.1.0")
|
||||
license_ = license_opt or click.prompt("License", default="Apache-2.0")
|
||||
include_frontend = (
|
||||
frontend_opt
|
||||
if frontend_opt is not None
|
||||
else click.confirm("Include frontend?", default=True)
|
||||
)
|
||||
include_backend = (
|
||||
backend_opt
|
||||
if backend_opt is not None
|
||||
else click.confirm("Include backend?", default=True)
|
||||
)
|
||||
|
||||
target_dir = Path.cwd() / id_
|
||||
if target_dir.exists():
|
||||
@@ -431,7 +469,7 @@ def init() -> None:
|
||||
"name": name,
|
||||
"include_frontend": include_frontend,
|
||||
"include_backend": include_backend,
|
||||
"license": license,
|
||||
"license": license_,
|
||||
"version": version,
|
||||
}
|
||||
|
||||
|
||||
@@ -360,3 +360,139 @@ def test_full_init_workflow_integration(cli_runner, isolated_filesystem):
|
||||
|
||||
pyproject_content = (extension_path / "backend" / "pyproject.toml").read_text()
|
||||
assert "awesome_charts" in pyproject_content
|
||||
|
||||
|
||||
# Non-interactive mode tests
|
||||
@pytest.mark.cli
|
||||
def test_init_non_interactive_with_all_options(cli_runner, isolated_filesystem):
|
||||
"""Test that init works in non-interactive mode with all CLI options."""
|
||||
result = cli_runner.invoke(
|
||||
app,
|
||||
[
|
||||
"init",
|
||||
"--id",
|
||||
"my_ext",
|
||||
"--name",
|
||||
"My Extension",
|
||||
"--version",
|
||||
"1.0.0",
|
||||
"--license",
|
||||
"MIT",
|
||||
"--frontend",
|
||||
"--backend",
|
||||
],
|
||||
)
|
||||
|
||||
assert result.exit_code == 0, f"Command failed with output: {result.output}"
|
||||
assert "🎉 Extension My Extension (ID: my_ext) initialized" in result.output
|
||||
|
||||
extension_path = isolated_filesystem / "my_ext"
|
||||
assert_directory_exists(extension_path)
|
||||
assert_directory_exists(extension_path / "frontend")
|
||||
assert_directory_exists(extension_path / "backend")
|
||||
|
||||
extension_json = load_json_file(extension_path / "extension.json")
|
||||
assert extension_json["id"] == "my_ext"
|
||||
assert extension_json["name"] == "My Extension"
|
||||
assert extension_json["version"] == "1.0.0"
|
||||
assert extension_json["license"] == "MIT"
|
||||
|
||||
|
||||
@pytest.mark.cli
|
||||
def test_init_frontend_only_with_cli_options(cli_runner, isolated_filesystem):
|
||||
"""Test init with frontend only using CLI options."""
|
||||
result = cli_runner.invoke(
|
||||
app,
|
||||
[
|
||||
"init",
|
||||
"--id",
|
||||
"frontend_ext",
|
||||
"--name",
|
||||
"Frontend Extension",
|
||||
"--version",
|
||||
"1.0.0",
|
||||
"--license",
|
||||
"MIT",
|
||||
"--frontend",
|
||||
"--no-backend",
|
||||
],
|
||||
)
|
||||
|
||||
assert result.exit_code == 0, f"Command failed with output: {result.output}"
|
||||
|
||||
extension_path = isolated_filesystem / "frontend_ext"
|
||||
assert_directory_exists(extension_path / "frontend")
|
||||
assert not (extension_path / "backend").exists()
|
||||
|
||||
|
||||
@pytest.mark.cli
|
||||
def test_init_backend_only_with_cli_options(cli_runner, isolated_filesystem):
|
||||
"""Test init with backend only using CLI options."""
|
||||
result = cli_runner.invoke(
|
||||
app,
|
||||
[
|
||||
"init",
|
||||
"--id",
|
||||
"backend_ext",
|
||||
"--name",
|
||||
"Backend Extension",
|
||||
"--version",
|
||||
"1.0.0",
|
||||
"--license",
|
||||
"MIT",
|
||||
"--no-frontend",
|
||||
"--backend",
|
||||
],
|
||||
)
|
||||
|
||||
assert result.exit_code == 0, f"Command failed with output: {result.output}"
|
||||
|
||||
extension_path = isolated_filesystem / "backend_ext"
|
||||
assert not (extension_path / "frontend").exists()
|
||||
assert_directory_exists(extension_path / "backend")
|
||||
|
||||
|
||||
@pytest.mark.cli
|
||||
def test_init_prompts_for_missing_options(cli_runner, isolated_filesystem):
|
||||
"""Test that init prompts for options not provided via CLI and uses defaults."""
|
||||
# Provide id and name via CLI, but version/license will be prompted (accept defaults)
|
||||
result = cli_runner.invoke(
|
||||
app,
|
||||
[
|
||||
"init",
|
||||
"--id",
|
||||
"default_ext",
|
||||
"--name",
|
||||
"Default Extension",
|
||||
"--frontend",
|
||||
"--backend",
|
||||
],
|
||||
input="\n\n", # Accept defaults for version and license prompts
|
||||
)
|
||||
|
||||
assert result.exit_code == 0, f"Command failed with output: {result.output}"
|
||||
|
||||
extension_path = isolated_filesystem / "default_ext"
|
||||
extension_json = load_json_file(extension_path / "extension.json")
|
||||
assert extension_json["version"] == "0.1.0"
|
||||
assert extension_json["license"] == "Apache-2.0"
|
||||
|
||||
|
||||
@pytest.mark.cli
|
||||
def test_init_non_interactive_validates_id(cli_runner, isolated_filesystem):
|
||||
"""Test that non-interactive mode validates extension ID."""
|
||||
result = cli_runner.invoke(
|
||||
app,
|
||||
[
|
||||
"init",
|
||||
"--id",
|
||||
"invalid-id",
|
||||
"--name",
|
||||
"Invalid Extension",
|
||||
"--frontend",
|
||||
"--backend",
|
||||
],
|
||||
)
|
||||
|
||||
assert result.exit_code == 1
|
||||
assert "must be alphanumeric" in result.output
|
||||
|
||||
Reference in New Issue
Block a user