Skip to content

Commit

Permalink
Add completer for tox 4 (#2415)
Browse files Browse the repository at this point in the history
Add completions for https://tox.wiki/

* Improve error handling for tox environments list
* Add comma separated environment support
* use carapace-parse to generate initial skeleton
- pipe all the 'tox subcommand --help' outputs to carapace-parse
- some minor manual editing
* add todo
* Switch to ActionExecCommand for tox listing environments
* refine completion for root args
* wip: list cmd
* fix issues in list command
* complete completions for config, depends, devenv, exec
* fix exec -- completion
* fix pkg-only, mark mutually exclusive with sdistonly
* add completions for run, run-parallel, quickstart
* add aliases, finish legacy subcommand
* consolidate common flags
* fmt
* address lints
* tox: minor changes

---------

Co-authored-by: rsteube <rsteube@users.noreply.github.com>
  • Loading branch information
samuelallan72 and rsteube authored Jul 8, 2024
1 parent f091a8c commit 3dab9d3
Show file tree
Hide file tree
Showing 12 changed files with 400 additions and 0 deletions.
32 changes: 32 additions & 0 deletions completers/tox_completer/cmd/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package cmd

import (
"github.com/carapace-sh/carapace"
"github.com/carapace-sh/carapace/pkg/style"
"github.com/spf13/cobra"
)

var configCmd = &cobra.Command{
Use: "config",
Aliases: []string{"c"},
Short: "show tox configuration",
Run: func(cmd *cobra.Command, args []string) {},
}

func init() {
carapace.Gen(configCmd).Standalone()

configCmd.Flags().Bool("core", false, "show core options (by default is hidden unless -e ALL is passed) (default: False)")
configCmd.Flags().Bool("develop", false, "install package in development mode (default: False)")
configCmd.Flags().StringS("k", "k", "", "list just configuration keys specified (default: [])")
configCmd.Flags().Bool("no-recreate-pkg", false, "if recreate is set do not recreate packaging tox environment(s) (default: False)")
configCmd.Flags().StringP("skip-missing-interpreters", "s", "config", "don't fail tests for missing interpreters: {config,true,false} choice (default: config)")
addCommonSubcommandFlags(configCmd)
addEnvFilteringFlags(configCmd)
addEnvSelectFlag(configCmd)
rootCmd.AddCommand(configCmd)

carapace.Gen(configCmd).FlagCompletion(carapace.ActionMap{
"skip-missing-interpreters": carapace.ActionValues("config", "true", "false").StyleF(style.ForKeyword),
})
}
20 changes: 20 additions & 0 deletions completers/tox_completer/cmd/depends.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package cmd

import (
"github.com/carapace-sh/carapace"
"github.com/spf13/cobra"
)

var dependsCmd = &cobra.Command{
Use: "depends",
Aliases: []string{"de"},
Short: "visualize tox environment dependencies",
Run: func(cmd *cobra.Command, args []string) {},
}

func init() {
carapace.Gen(dependsCmd).Standalone()

addCommonSubcommandFlags(dependsCmd)
rootCmd.AddCommand(dependsCmd)
}
32 changes: 32 additions & 0 deletions completers/tox_completer/cmd/devenv.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package cmd

import (
"github.com/carapace-sh/carapace"
"github.com/carapace-sh/carapace-bin/pkg/actions/tools/tox"
"github.com/spf13/cobra"
)

var devenvCmd = &cobra.Command{
Use: "devenv",
Aliases: []string{"d"},
Short: "sets up a development environment at ENVDIR based on the tox configuration specified",
Run: func(cmd *cobra.Command, args []string) {},
}

func init() {
carapace.Gen(devenvCmd).Standalone()

devenvCmd.Flags().StringS("e", "e", "", "environment to run (default: py)")
devenvCmd.Flags().Bool("no-recreate-pkg", false, "if recreate is set do not recreate packaging tox environment(s) (default: False)")
devenvCmd.Flags().String("skip-env", "", "exclude all environments selected that match this regular expression (default: '')")
addCommonSubcommandFlags(devenvCmd)
rootCmd.AddCommand(devenvCmd)

carapace.Gen(devenvCmd).FlagCompletion(carapace.ActionMap{
"e": tox.ActionEnvironments(),
})

carapace.Gen(devenvCmd).PositionalCompletion(
carapace.ActionDirectories(),
)
}
34 changes: 34 additions & 0 deletions completers/tox_completer/cmd/exec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package cmd

import (
"github.com/carapace-sh/carapace"
"github.com/carapace-sh/carapace-bin/pkg/actions/tools/tox"
"github.com/carapace-sh/carapace-bridge/pkg/actions/bridge"
"github.com/spf13/cobra"
)

var execCmd = &cobra.Command{
Use: "exec",
Aliases: []string{"e"},
Short: "execute an arbitrary command within a tox environment",
Run: func(cmd *cobra.Command, args []string) {},
}

func init() {
carapace.Gen(execCmd).Standalone()

execCmd.Flags().StringS("e", "e", "", "environment to run (default: py)")
execCmd.Flags().String("skip-env", "", "exclude all environments selected that match this regular expression (default: '')")
addCommonSubcommandFlags(execCmd)
addPkgOnlyFlags(execCmd)
addCommonRunFlags(execCmd)
rootCmd.AddCommand(execCmd)

carapace.Gen(execCmd).FlagCompletion(carapace.ActionMap{
"e": tox.ActionEnvironments(),
})

carapace.Gen(execCmd).DashAnyCompletion(
bridge.ActionCarapaceBin(),
)
}
42 changes: 42 additions & 0 deletions completers/tox_completer/cmd/legacy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package cmd

import (
"github.com/carapace-sh/carapace"
"github.com/spf13/cobra"
)

var legacyCmd = &cobra.Command{
Use: "legacy",
Aliases: []string{"l"},
Short: "legacy entry-point command",
Run: func(cmd *cobra.Command, args []string) {},
}

func add_legacy_flags(cmd *cobra.Command) {
cmd.Flags().String("devenv", "", "sets up a development environment at ENVDIR based on the env's tox configuration specified by`-e` (-e defaults to py) (default: None)")
cmd.Flags().Bool("help-ini", false, "show live configuration (default: False)")
cmd.Flags().Bool("hi", false, "show live configuration (default: False)")
cmd.MarkFlagsMutuallyExclusive("help-ini", "hi")
cmd.Flags().Bool("alwayscopy", false, "deprecated use VIRTUALENV_ALWAYS_COPY=1, override always copy setting to True in all envs (default: False)")
cmd.Flags().StringArray("force-dep", []string{}, "Forces a certain version of one of the dependencies when configuring the virtual environment. REQ Examples 'pytest<6.1' or 'django>=2.2'. (default: [])")
cmd.Flags().BoolP("listenvs", "l", false, "show list of test environments (with description if verbose) (default: False)")
cmd.Flags().BoolP("listenvs-all", "a", false, "show list of all defined environments (with description if verbose) (default: False)")
cmd.Flags().StringP("parallel", "p", "0", "run tox environments in parallel, the argument controls limit: all, auto - cpu count, some positive number, zero is turn off (default: 0)")
cmd.Flags().BoolP("parallel-live", "o", false, "connect to stdout while running environments")
cmd.Flags().Bool("parallel-no-spinner", false, "run tox environments in parallel, but don't show the spinner, implies --parallel")
cmd.Flags().Bool("pre", false, "deprecated use PIP_PRE in set_env instead - install pre-releases and development versions ofdependencies; this will set PIP_PRE=1 environment variable (default: False)")
cmd.Flags().Bool("showconfig", false, "show live configuration (by default all env, with -l only default targets, specific via TOXENV/-e) (default: False)")
cmd.Flags().Bool("sitepackages", false, "deprecated use VIRTUALENV_SYSTEM_SITE_PACKAGES=1, override sitepackages setting to True in all envs (default: False)")
addCommonSubcommandFlags(cmd)
addPkgOnlyFlags(cmd)
addEnvFilteringFlags(cmd)
addEnvSelectFlag(cmd)
addCommonRunFlags(cmd)
}

func init() {
carapace.Gen(legacyCmd).Standalone()

add_legacy_flags(legacyCmd)
rootCmd.AddCommand(legacyCmd)
}
21 changes: 21 additions & 0 deletions completers/tox_completer/cmd/list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package cmd

import (
"github.com/carapace-sh/carapace"
"github.com/spf13/cobra"
)

var listCmd = &cobra.Command{
Use: "list",
Aliases: []string{"l"},
Short: "list environments",
Run: func(cmd *cobra.Command, args []string) {},
}

func init() {
carapace.Gen(listCmd).Standalone()

listCmd.Flags().BoolS("d", "d", false, "list just default envs (default: False)")
addEnvFilteringFlags(listCmd)
rootCmd.AddCommand(listCmd)
}
23 changes: 23 additions & 0 deletions completers/tox_completer/cmd/quickstart.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package cmd

import (
"github.com/carapace-sh/carapace"
"github.com/spf13/cobra"
)

var quickstartCmd = &cobra.Command{
Use: "quickstart",
Aliases: []string{"q"},
Short: "Command line script to quickly create a tox config file for a Python project",
Run: func(cmd *cobra.Command, args []string) {},
}

func init() {
carapace.Gen(quickstartCmd).Standalone()

rootCmd.AddCommand(quickstartCmd)

carapace.Gen(quickstartCmd).PositionalCompletion(
carapace.ActionDirectories(),
)
}
109 changes: 109 additions & 0 deletions completers/tox_completer/cmd/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package cmd

import (
"github.com/carapace-sh/carapace"
"github.com/carapace-sh/carapace-bin/pkg/actions/tools/tox"
"github.com/carapace-sh/carapace/pkg/style"
"github.com/carapace-sh/carapace/pkg/traverse"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)

var rootCmd = &cobra.Command{
Use: "tox",
Short: "automation project",
Long: "https://tox.wiki/",
Run: func(cmd *cobra.Command, args []string) {},
}

func Execute() error {
return rootCmd.Execute()
}

func init() {
carapace.Gen(rootCmd).Standalone()

rootCmd.PersistentFlags().String("colored", "", "should output be enriched with colors, default is yes unless TERM=dumb or NO_COLOR is defined. (default: no)")
rootCmd.PersistentFlags().StringP("conf", "c", "", "configuration file/folder for tox (if not specified will discover one) (default: None)")
rootCmd.PersistentFlags().Uint("exit-and-dump-after", 0, "dump tox threads after n seconds and exit the app - useful to debug when tox hangs, 0 means disabled (default: 0)")
rootCmd.PersistentFlags().BoolP("help", "h", false, "show this help message and exit")
rootCmd.PersistentFlags().String("no-provision", "", "do not perform provision, but fail and if a path was provided write provision metadata as JSON to it (default: False)")
rootCmd.PersistentFlags().Bool("no-recreate-provision", false, "if recreate is set do not recreate provision tox environment (default: False)")
rootCmd.PersistentFlags().StringArrayP("override", "x", []string{}, "configuration override(s), e.g., -x testenv:pypy3.ignore_errors=True (default: [])")
rootCmd.PersistentFlags().CountP("quiet", "q", "decrease verbosity (default: 0)")
rootCmd.PersistentFlags().BoolP("recreate", "r", false, "recreate the tox environments (default: False)")
rootCmd.PersistentFlags().String("root", "", "project root directory (if not specified will be the folder of the config file) (default: None)")
rootCmd.PersistentFlags().String("runner", "virtualenv", "the tox run engine to use when not explicitly stated in tox env configuration (default: virtualenv)")
rootCmd.PersistentFlags().Bool("version", false, "show program's and plugins version number and exit")
rootCmd.PersistentFlags().CountP("verbose", "v", "increase verbosity (default: 2)")
rootCmd.PersistentFlags().String("workdir", "", "tox working directory (if not specified will be the folder of the config file) (default: None)")
add_legacy_flags(rootCmd)

carapace.Gen(rootCmd).FlagCompletion(carapace.ActionMap{
"colored": carapace.ActionValues("yes", "no").StyleF(style.ForKeyword),
"conf": carapace.ActionFiles(),
"root": carapace.ActionDirectories(),
"workdir": carapace.ActionDirectories(),
})

carapace.Gen(rootCmd).PreInvoke(func(cmd *cobra.Command, flag *pflag.Flag, action carapace.Action) carapace.Action {
return action.ChdirF(traverse.Flag(cmd.Flag("workdir")))
})
}

// addCommonSubcommandFlags defines the flags on a tox subcommand that are common across a majority of subcommands.
func addCommonSubcommandFlags(cmd *cobra.Command) {
cmd.Flags().StringArray("discover", []string{}, "for Python discovery first try these Python executables (default: [])")
cmd.Flags().String("hashseed", "", "set PYTHONHASHSEED to SEED before running commands. Defaults to a random integer in the range [1, 4294967295] ([1, 1024] on Windows). Passing 'notset' suppresses this behavior. (default: 264197440)")
cmd.Flags().Bool("list-dependencies", false, "list the dependencies installed during environment setup (default: False)")
cmd.Flags().Bool("no-list-dependencies", false, "never list the dependencies installed during environment setup (default: True)")
cmd.Flags().String("result-json", "", "write a JSON file with detailed information about all commands and results involved (default: None)")

cmd.Flag("discover").Nargs = -1

carapace.Gen(cmd).FlagCompletion(carapace.ActionMap{
"discover": carapace.ActionFiles(),
"result-json": carapace.ActionFiles(),
})
}

// addPkgOnlyFlags adds the pkg-only / sdistonly group of flags
func addPkgOnlyFlags(cmd *cobra.Command) {
// these two are the same flag; there are two long flags for this
cmd.Flags().BoolP("pkg-only", "b", false, "only perform the packaging activity")
cmd.Flags().Bool("sdistonly", false, "only perform the packaging activity")
cmd.MarkFlagsMutuallyExclusive("pkg-only", "sdistonly")
}

// addEnvFilteringFlags adds the -m, -f, and --skip-env flags
func addEnvFilteringFlags(cmd *cobra.Command) {
cmd.Flags().StringArrayS("f", "f", []string{}, "factors to evaluate (passing multiple factors means 'AND', passing this option multiple times means 'OR') (default: [])")
cmd.Flags().StringArrayS("m", "m", []string{}, "labels to evaluate (default: [])")
cmd.Flags().String("skip-env", "", "exclude all environments selected that match this regular expression (default: '')")

cmd.Flag("f").Nargs = -1
cmd.Flag("m").Nargs = -1
}

// addEnvSelectFlag adds the -e flag for multiple environments
func addEnvSelectFlag(cmd *cobra.Command) {
cmd.Flags().StringS("e", "e", "", "enumerate, comma separated (ALL -> all environments, not set -> use <env_list> from config) (default: <env_list>)")

carapace.Gen(cmd).FlagCompletion(carapace.ActionMap{
"e": tox.ActionEnvironments().UniqueList(","),
})
}

// addCommonRunFlags adds flags common to subcommonds that run something in an environment
func addCommonRunFlags(cmd *cobra.Command) {
cmd.Flags().Bool("develop", false, "install package in development mode (default: False)")
cmd.Flags().String("installpkg", "", "use specified package for installation into venv, instead of packaging the project (default: None)")
cmd.Flags().Bool("no-recreate-pkg", false, "if recreate is set do not recreate packaging tox environment(s) (default: False)")
cmd.Flags().BoolP("notest", "n", false, "do not run the test commands (default: False)")
cmd.Flags().StringP("skip-missing-interpreters", "s", "config", "don't fail tests for missing interpreters: {config,true,false} choice (default: config)")
cmd.Flags().Bool("skip-pkg-install", false, "skip package installation for this run (default: False)")

carapace.Gen(cmd).FlagCompletion(carapace.ActionMap{
"skip-missing-interpreters": carapace.ActionValues("config", "true", "false").StyleF(style.ForKeyword),
})
}
25 changes: 25 additions & 0 deletions completers/tox_completer/cmd/run.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package cmd

import (
"github.com/carapace-sh/carapace"
"github.com/spf13/cobra"
)

var runCmd = &cobra.Command{
Use: "run",
Aliases: []string{"r"},
Short: "run environments",
Run: func(cmd *cobra.Command, args []string) {},
}

func init() {
carapace.Gen(runCmd).Standalone()

addCommonSubcommandFlags(runCmd)
addPkgOnlyFlags(runCmd)
addEnvFilteringFlags(runCmd)
addEnvSelectFlag(runCmd)
addCommonRunFlags(runCmd)

rootCmd.AddCommand(runCmd)
}
32 changes: 32 additions & 0 deletions completers/tox_completer/cmd/run_parallel.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package cmd

import (
"github.com/carapace-sh/carapace"
"github.com/carapace-sh/carapace/pkg/style"
"github.com/spf13/cobra"
)

var runParallelCmd = &cobra.Command{
Use: "run-parallel",
Aliases: []string{"p"},
Short: "run environments in parallel",
Run: func(cmd *cobra.Command, args []string) {},
}

func init() {
carapace.Gen(runParallelCmd).Standalone()

runParallelCmd.Flags().StringP("parallel", "p", "auto", "run tox environments in parallel, the argument controls limit: all, auto - cpu count, some positive number, zero is turn off (default: auto)")
runParallelCmd.Flags().BoolP("parallel-live", "o", false, "connect to stdout while running environments")
runParallelCmd.Flags().Bool("parallel-no-spinner", false, "run tox environments in parallel, but don't show the spinner, implies --parallel")
addCommonSubcommandFlags(runParallelCmd)
addPkgOnlyFlags(runParallelCmd)
addEnvFilteringFlags(runParallelCmd)
addEnvSelectFlag(runParallelCmd)
addCommonRunFlags(runParallelCmd)
rootCmd.AddCommand(runParallelCmd)

carapace.Gen(runParallelCmd).FlagCompletion(carapace.ActionMap{
"parallel": carapace.ActionValues("all", "auto", "0").StyleF(style.ForKeyword), // or any positive integer
})
}
7 changes: 7 additions & 0 deletions completers/tox_completer/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package main

import "github.com/carapace-sh/carapace-bin/completers/tox_completer/cmd"

func main() {
cmd.Execute()
}
Loading

0 comments on commit 3dab9d3

Please sign in to comment.