product:commands

Table of contents

  1. Introduction
  2. Adding a command to a feature
  3. Adding a command to the product
  4. Advanced

Introduction

product:commands lists the CLI commands your product’s features contribute, and your product’s own. It needs a selected product (SPLENT_APP) whose app boots.

splent product:commands
  Feature Commands

  Feature  Command                     Flags                Description
  -------  --------------------------  -------------------  ------------------------------
  notes    feature:notes export-notes  --format FORMAT      Print every note of the acti...
           feature:notes purge-drafts  --older-than DAYS *  Delete the drafts older than...

  2 command(s) from 1 feature(s).

  Product Commands

  Product   Command            Flags              Description
  --------  -----------------  -----------------  ------------------------------
  my_shop   product:reprice    --dry-run          Recompute every price from...

  1 command(s) of my_shop's own.

Feature is the short name, without splent_feature_. Flags lists each option with its value type, and * marks a required one.


Adding a command to a feature

Give the feature a commands.py with a cli_commands list.

# splent_feature_notes/commands.py
import click
from splent_framework.services.service_locator import service_proxy

@click.command("purge-drafts")
@click.option("--older-than", required=True, type=int, metavar="DAYS", help="Age in days.")
def purge_drafts(older_than):
    """Delete the drafts older than a number of days."""
    count = service_proxy("NotesService").purge_drafts(days=older_than)
    click.secho(f"  Deleted {count} draft(s).", fg="green")

cli_commands = [purge_drafts]

The framework finds it when it loads the feature, and the CLI exposes the command under feature:<name>.

splent feature:notes purge-drafts --older-than 30

feature:contract --write records the commands in the feature’s contract. Only the features your product declares contribute commands.


Adding a command to the product

Your product declares its own commands the same way, in <product>/src/<product>/commands.py. Name them without a prefix.

# my_shop/src/my_shop/commands.py
import click


@click.command("reprice")
@click.option("--dry-run", is_flag=True, help="Say what would change.")
def reprice(dry_run):
    """Recompute every price from the catalogue."""
    ...


cli_commands = [reprice]

The CLI runs each one as product:<name>, in your product’s app context.

splent product:reprice --dry-run

splent --help lists them under Product Commands.

A built-in command always wins. A product command named test would be product:test, which is the CLI’s, so it cannot be reached. product:commands warns with ⚠ my_shop has a command product:test, which is the CLI's own and wins: rename it to reach it.


Advanced

When the CLI’s container cannot build the app because a feature needs a package only the product’s image has, a feature:<name> or product:<name> command runs in the product’s web container.

A product commands.py that fails to import leaves its commands out, and the built-ins still work. product:commands says why, as in ⚠ my_shop's own commands are not available: my_shop.commands: No module named '...'.

While the product is deployed, these commands run against the production app and database, which is how a command that creates the first account works there. See the CLI while production is deployed.


Back to top

splent. Distributed by an LGPL license v3. Contact us: drorganvidez@us.es