From 8c4a4fbf9eddf0605f5e0698e9756f506bb401ac Mon Sep 17 00:00:00 2001 From: kxue43 Date: Wed, 17 Dec 2025 13:21:17 -0500 Subject: [PATCH 1/2] feat: Use `ruff` in place of `flake8` and `black`. --- .../workflows/test-and-lint.yaml.tmplt | 2 +- scaffold/.go/.pre-commit-config.yaml.tmplt | 4 +- scaffold/.python/.flake8.tmplt | 7 - .../.python/.pre-commit-config.yaml.tmplt | 14 +- scaffold/.python/pyproject.toml.tmplt | 17 +- scaffold/project.go | 161 +++++++++++------- scaffold/project_test.go | 100 ++++++----- tui/tui.go | 2 +- 8 files changed, 165 insertions(+), 142 deletions(-) delete mode 100644 scaffold/.python/.flake8.tmplt diff --git a/scaffold/.go/.github/workflows/test-and-lint.yaml.tmplt b/scaffold/.go/.github/workflows/test-and-lint.yaml.tmplt index 834e4ad..c60b1a0 100644 --- a/scaffold/.go/.github/workflows/test-and-lint.yaml.tmplt +++ b/scaffold/.go/.github/workflows/test-and-lint.yaml.tmplt @@ -38,4 +38,4 @@ jobs: - name: Lint with golangci-lint uses: golangci/golangci-lint-action@v8 with: - version: "{% .GolangcilintTag %}" + version: v{% .GolangcilintVersion %} diff --git a/scaffold/.go/.pre-commit-config.yaml.tmplt b/scaffold/.go/.pre-commit-config.yaml.tmplt index 2eae8e8..790e7e8 100644 --- a/scaffold/.go/.pre-commit-config.yaml.tmplt +++ b/scaffold/.go/.pre-commit-config.yaml.tmplt @@ -1,12 +1,12 @@ repos: - repo: https://github.com/golangci/golangci-lint - rev: "{% .GolangcilintTag %}" + rev: v{% .GolangcilintVersion %} hooks: - id: golangci-lint-config-verify - id: golangci-lint-fmt - id: golangci-lint-full - repo: https://github.com/godaddy/tartufo - rev: "{% .TartufoTag %}" + rev: v{% .TartufoVersion %} hooks: - id: tartufo diff --git a/scaffold/.python/.flake8.tmplt b/scaffold/.python/.flake8.tmplt deleted file mode 100644 index b6ee3ea..0000000 --- a/scaffold/.python/.flake8.tmplt +++ /dev/null @@ -1,7 +0,0 @@ -[flake8] -max-line-length = 88 -extend-ignore = E203,E501 -exclude = .svn,CVS,.bzr,.hg,.git,__pycache__,.tox,.eggs,*.egg,build,dist -filename = *.py -per-file-ignores = - adhoc*.py:E402,F401,F811 diff --git a/scaffold/.python/.pre-commit-config.yaml.tmplt b/scaffold/.python/.pre-commit-config.yaml.tmplt index 1a2fef8..ddbc162 100644 --- a/scaffold/.python/.pre-commit-config.yaml.tmplt +++ b/scaffold/.python/.pre-commit-config.yaml.tmplt @@ -1,13 +1,9 @@ repos: - - repo: https://github.com/psf/black - rev: "{% .BlackVersion %}" + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v{% .RuffVersion %} hooks: - - id: black - - - repo: https://github.com/PyCQA/flake8 - rev: "{% .Flake8Version %}" - hooks: - - id: flake8 + - id: ruff-check + - id: ruff-format - repo: https://github.com/kxue43/shell-cmd-on-change rev: "2.0.0" @@ -23,6 +19,6 @@ repos: verbose: true - repo: https://github.com/godaddy/tartufo - rev: "{% .TartufoTag %}" + rev: v{% .TartufoVersion %} hooks: - id: tartufo diff --git a/scaffold/.python/pyproject.toml.tmplt b/scaffold/.python/pyproject.toml.tmplt index 9c90b0c..1b9f43d 100644 --- a/scaffold/.python/pyproject.toml.tmplt +++ b/scaffold/.python/pyproject.toml.tmplt @@ -27,28 +27,23 @@ default-groups = [ [dependency-groups] linting = [ - "black=={% .BlackVersion %}", # This version must be the same as in `./.pre-commit-config.yaml`. - "flake8=={% .Flake8Version %}", # This version must be the same as in `./.pre-commit-config.yaml`. - "mypy~={% .MypyVersion %}", + "ruff~={% .RuffVersion.MajorMinor %}", + "mypy~={% .MypyVersion.MajorMinor %}", ] test = [ - "pytest~={% .PytestVersion %}", - "pytest-mock~={% .PytestMockVersion %}", - "pytest-cov~={% .PytestCovVersion %}", + "pytest~={% .PytestVersion.MajorMinor %}", + "pytest-mock~={% .PytestMockVersion.MajorMinor %}", + "pytest-cov~={% .PytestCovVersion.MajorMinor %}", ] docs = [ - "sphinx~={% .SphinxVersion %}", + "sphinx~={% .SphinxVersion.MajorMinor %}", "sphinx-rtd-theme", "sphinx-autodoc-typehints", "sphinx-copybutton", ] -[tool.black] -line-length = 88 -target-version = ["py{% .PythonVersion.NumsOnly %}"] - [tool.pytest.ini_options] testpaths = ["tests"] addopts = "--cov=src --cov-report term-missing" diff --git a/scaffold/project.go b/scaffold/project.go index 6df6ef4..a00315f 100644 --- a/scaffold/project.go +++ b/scaffold/project.go @@ -23,27 +23,26 @@ import ( type ( GoProjectCmd struct { - rootDir string - ModulePath string `arg:"" required:"" name:"ModulePath" help:"Module path for the project."` - GoVersion string `name:"go-version" default:"1.24.1" help:"Will appear in go.mod and GitHub Actions workflow."` - GolangcilintTag string `name:"golangci-lint-tag" default:"LATEST" help:"GitHub tag of golangci-lint."` - TartufoTag string `name:"tartufo-tag" default:"LATEST" help:"GitHub tag of tartufo."` - VersionSetters []VersionSetter `kong:"-"` - TimeoutSeconds int `name:"timeout-seconds" default:"1" help:"Timeout scaffolding after this many seconds."` + rootDir string + ModulePath string `arg:"" required:"" name:"ModulePath" help:"Module path for the project."` + GoVersion string `name:"go-version" default:"1.24.1" help:"Will appear in go.mod and GitHub Actions workflow."` + GolangcilintVersion SemVer `name:"golangci-lint-version" default:"LATEST" help:"Version of golangci-lint, a pre-commit hook."` + TartufoVersion SemVer `name:"tartufo-version" default:"LATEST" help:"Version of tartufo, a pre-commit hook."` + VersionSetters []VersionSetter `kong:"-"` + TimeoutSeconds int `name:"timeout-seconds" default:"1" help:"Timeout scaffolding after this many seconds."` } PythonProjectCmd struct { rootDir string ProjectName string `arg:"" required:"" name:"ProjectName" help:"Python project name."` Description string `name:"description" default:"PLACEHOLDER" help:"Short description of the project"` - BlackVersion string `name:"black-version" default:"LATEST" help:"Exact major.minor.bugfix version of black."` - Flake8Version string `name:"flake8-version" default:"LATEST" help:"Exact major.minor.bugfix version of flake8."` - TartufoTag string `name:"tartufo-tag" default:"LATEST" help:"GitHub tag of tartufo."` - MypyVersion string `name:"mypy-version" default:"LATEST" help:"Major and minor version of the format X.Y for mypy."` - PytestVersion string `name:"pytest-version" default:"LATEST" help:"Major and minor version of the format X.Y for pytest."` - PytestMockVersion string `name:"pytest-mock-version" default:"LATEST" help:"Major and minor version of the format X.Y for pytest-mock."` - PytestCovVersion string `name:"pytest-cov-version" default:"LATEST" help:"Major and minor version of the format X.Y for pytest-cov."` - SphinxVersion string `name:"sphinx-version" default:"LATEST" help:"Major and minor version of the format X.Y for sphinx."` + TartufoVersion SemVer `name:"tartufo-version" default:"LATEST" help:"Version of tartufo, a pre-commit hook."` + RuffVersion SemVer `name:"ruff-version" default:"LATEST" help:"Version of ruff, a linting dependency."` + MypyVersion SemVer `name:"mypy-version" default:"LATEST" help:"Version of mypy, a linting dependency."` + PytestVersion SemVer `name:"pytest-version" default:"LATEST" help:"Version of pytest, a test dependency."` + PytestMockVersion SemVer `name:"pytest-mock-version" default:"LATEST" help:"Version of pytest-mock, a test dependency."` + PytestCovVersion SemVer `name:"pytest-cov-version" default:"LATEST" help:"Version of pytest-cov, a test dependency."` + SphinxVersion SemVer `name:"sphinx-version" default:"LATEST" help:"Version of sphinx, a doc dependency."` PythonVersion PythonVersion `name:"python-version" required:"" help:"Python 3 interpreter version. Only accept major and minor version, i.e. the 3.Y format."` VersionSetters []VersionSetter `kong:"-"` TimeoutSeconds int `name:"timeout-seconds" default:"1" help:"Timeout scaffolding after this many seconds."` @@ -52,20 +51,20 @@ type ( TsCdkProjectCmd struct { rootDir string ProjectName string `arg:"" required:"" name:"ProjectName" help:"TypeScript CDK project name."` - EslintVersion string `name:"eslint-version" default:"LATEST" help:"Will appear in package.json."` - EslintJsVersion string `name:"eslint-js-version" default:"LATEST" help:"Will appear in package.json."` - TypeScriptEslintVersion string `name:"typescript-eslint-version" default:"LATEST" help:"Will appear in package.json."` - VitestVersion string `name:"vitest-version" default:"LATEST" help:"Will appear in package.json."` - VitestCoverageV8Version string `name:"vitest-coverage-v8-version" default:"LATEST" help:"Will appear in package.json."` - AwsCdkCliVersion string `name:"aws-cdk-cli-version" default:"LATEST" help:"Will appear in package.json."` - EsbuildVersion string `name:"esbuild-version" default:"LATEST" help:"Will appear in package.json."` - PrettierVersion string `name:"prettier-version" default:"LATEST" help:"Will appear in package.json."` - TsxVersion string `name:"tsx-version" default:"LATEST" help:"Will appear in package.json."` - TypeScriptVersion string `name:"typescript-version" default:"LATEST" help:"Will appear in package.json."` - AwsCdkAssertVersion string `name:"aws-cdk-assert-version" default:"LATEST" help:"Will appear in package.json."` - AwsCdkLibVersion string `name:"aws-cdk-lib-version" default:"LATEST" help:"Will appear in package.json."` - ConstructsVersion string `name:"constructs-version" default:"LATEST" help:"Will appear in package.json."` - YamlVersion string `name:"yaml-version" default:"LATEST" help:"Will appear in package.json."` + EslintVersion SemVer `name:"eslint-version" default:"LATEST" help:"Version of eslint, a dev dependency."` + EslintJsVersion SemVer `name:"eslint-js-version" default:"LATEST" help:"Version of eslint-js, a dev dependency."` + TypeScriptEslintVersion SemVer `name:"typescript-eslint-version" default:"LATEST" help:"Version of typescript-eslint, a dev dependency."` + VitestVersion SemVer `name:"vitest-version" default:"LATEST" help:"Version of vitest, a test dependency."` + VitestCoverageV8Version SemVer `name:"vitest-coverage-v8-version" default:"LATEST" help:"Version of vitest-coverage, a test dependency."` + AwsCdkCliVersion SemVer `name:"aws-cdk-cli-version" default:"LATEST" help:"Version of the AWS CDK CLI."` + AwsCdkLibVersion SemVer `name:"aws-cdk-lib-version" default:"LATEST" help:"Version of the AWS CDK library."` + ConstructsVersion SemVer `name:"constructs-version" default:"LATEST" help:"Version of the constructs library."` + EsbuildVersion SemVer `name:"esbuild-version" default:"LATEST" help:"Version of esbuild, a dev dependency."` + PrettierVersion SemVer `name:"prettier-version" default:"LATEST" help:"Version of prettier, a dev dependency."` + TsxVersion SemVer `name:"tsx-version" default:"LATEST" help:"Version of tsx, a dev dependency."` + TypeScriptVersion SemVer `name:"typescript-version" default:"LATEST" help:"Version of typescript."` + AwsCdkAssertVersion SemVer `name:"aws-cdk-assert-version" default:"LATEST" help:"Version of aws-cdk-assert, a test dependency."` + YamlVersion SemVer `name:"yaml-version" default:"LATEST" help:"Version of yaml, a test dependency."` NodejsVersion NodejsVersion `name:"nodejs-version" required:"" help:"Only accept major and minor version, i.e. the X.Y format."` VersionSetters []VersionSetter `kong:"-"` TimeoutSeconds int `name:"timeout-seconds" default:"1" help:"Timeout scaffolding after this many seconds."` @@ -83,14 +82,20 @@ type ( Minor string } + SemVer struct { + major string + minor string + bugfix string + set bool + } + Registry byte VersionSetter struct { - Indirect *string - Scope string - Name string - Registry Registry - MajorMinorOnly bool + Indirect *SemVer + Scope string + Name string + Registry Registry } setterFunc func(context.Context) error @@ -120,7 +125,7 @@ var ( tmpltExt = ".tmplt" - versionRegex = regexp.MustCompile(`^(?:v)?(\d+\.\d+)(?:\.\d+)?$`) + semVerRegex = regexp.MustCompile(`^(\d+)\.(\d+)(\..+)?$`) ) func (pv *PythonVersion) UnmarshalText(text []byte) error { @@ -128,7 +133,7 @@ func (pv *PythonVersion) UnmarshalText(text []byte) error { m := regex.FindStringSubmatch(string(text)) if len(m) == 0 { - return fmt.Errorf(`%s is not of the "3\.(\d+)" format`, string(text)) + return fmt.Errorf(`%s is not of the %s format`, string(text), regex) } pv.Major = "3" @@ -150,7 +155,7 @@ func (nv *NodejsVersion) UnmarshalText(text []byte) error { m := regex.FindStringSubmatch(string(text)) if len(m) == 0 { - return fmt.Errorf(`%s is not of the "(\d+)\.(\d+)" format`, string(text)) + return fmt.Errorf(`%s is not of the %s format`, string(text), regex) } nv.Major = m[1] @@ -163,6 +168,47 @@ func (nv *NodejsVersion) String() string { return nv.Major + "." + nv.Minor } +func (sv *SemVer) String() string { + return fmt.Sprintf("%s.%s.%s", sv.major, sv.minor, sv.bugfix) +} + +func (sv *SemVer) MajorMinor() string { + return fmt.Sprintf("%s.%s", sv.major, sv.minor) +} + +func (sv *SemVer) UnmarshalText(text []byte) error { + if strings.EqualFold(string(text), "LATEST") { + return nil + } + + m := semVerRegex.FindStringSubmatch(string(text)) + if len(m) == 0 { + return fmt.Errorf(`%s is not of the %s format`, string(text), semVerRegex) + } + + sv.major = m[1] + sv.minor = m[2] + sv.bugfix = "0" + + if m[3] != "" { + sv.bugfix = strings.TrimPrefix(m[3], ".") + } + + sv.set = true + + return nil +} + +func (sv *SemVer) SetFromString(raw string) error { + raw = strings.TrimPrefix(raw, "v") + + return sv.UnmarshalText([]byte(raw)) +} + +func (sv *SemVer) Set() bool { + return sv.set +} + func ToModFile(modulePath, goVersion string) WriteHook { return func(fd io.Writer) error { goModFile := new(modfile.File) @@ -367,31 +413,29 @@ func writeFiles(dest string, srcFS embed.FS, srcPrefix string, data any) (err er } func (vs VersionSetter) Func(ctx context.Context) (err error) { + var rawSpecifier string + switch vs.Registry { case GitHub: - *vs.Indirect, err = GitHubProjectLatestReleaseTag(ctx, vs.Scope, vs.Name) + rawSpecifier, err = GitHubProjectLatestReleaseTag(ctx, vs.Scope, vs.Name) if err != nil { - return fmt.Errorf("failed to fetch the latest version of %s/%s from GitHub: %w", vs.Scope, vs.Name, err) + return fmt.Errorf("failed to fetch the latest tag of %s/%s from GitHub: %w", vs.Scope, vs.Name, err) } case PyPI: - *vs.Indirect, err = PyPIPackageLatestVersion(ctx, vs.Name) + rawSpecifier, err = PyPIPackageLatestVersion(ctx, vs.Name) if err != nil { return fmt.Errorf("failed to fetch the latest version of %s from PyPI: %w", vs.Name, err) } case NPM: - *vs.Indirect, err = NPMPackageLatestVersion(ctx, vs.Name) + rawSpecifier, err = NPMPackageLatestVersion(ctx, vs.Name) if err != nil { return fmt.Errorf("failed to fetch the latest version of %s from NPM: %w", vs.Name, err) } } - if vs.MajorMinorOnly { - m := versionRegex.FindStringSubmatch(*vs.Indirect) - if len(m) == 0 { - return fmt.Errorf("failed to extract major and minor versions from %q for package %s", *vs.Indirect, vs.Name) - } - - *vs.Indirect = m[1] + err = vs.Indirect.SetFromString(rawSpecifier) + if err != nil { + return fmt.Errorf("failed to parse %q as a semantic version specifier: %s", rawSpecifier, err.Error()) } return nil @@ -401,7 +445,7 @@ func getSetterFuncs(vss []VersionSetter) []setterFunc { setterFuncs := make([]setterFunc, 0, len(vss)) for i := range vss { - if *vss[i].Indirect == "LATEST" { + if !vss[i].Indirect.Set() { setterFuncs = append(setterFuncs, vss[i].Func) } } @@ -435,8 +479,8 @@ func setVersions(ctx context.Context, fns []setterFunc) error { func (c *GoProjectCmd) BeforeReset() error { c.VersionSetters = []VersionSetter{ - {Registry: GitHub, Scope: "golangci", Name: "golangci-lint", Indirect: &c.GolangcilintTag}, - {Registry: GitHub, Scope: "godaddy", Name: "tartufo", Indirect: &c.TartufoTag}, + {Registry: GitHub, Scope: "golangci", Name: "golangci-lint", Indirect: &c.GolangcilintVersion}, + {Registry: GitHub, Scope: "godaddy", Name: "tartufo", Indirect: &c.TartufoVersion}, } return nil @@ -471,14 +515,13 @@ func (c *GoProjectCmd) Run() (err error) { func (c *PythonProjectCmd) BeforeReset() error { c.VersionSetters = []VersionSetter{ - {Registry: GitHub, Scope: "psf", Name: "black", Indirect: &c.BlackVersion}, - {Registry: PyPI, Name: "flake8", Indirect: &c.Flake8Version}, - {Registry: PyPI, Name: "mypy", Indirect: &c.MypyVersion, MajorMinorOnly: true}, - {Registry: PyPI, Name: "pytest", Indirect: &c.PytestVersion, MajorMinorOnly: true}, - {Registry: PyPI, Name: "pytest-mock", Indirect: &c.PytestMockVersion, MajorMinorOnly: true}, - {Registry: PyPI, Name: "pytest-cov", Indirect: &c.PytestCovVersion, MajorMinorOnly: true}, - {Registry: PyPI, Name: "Sphinx", Indirect: &c.SphinxVersion, MajorMinorOnly: true}, - {Registry: GitHub, Scope: "godaddy", Name: "tartufo", Indirect: &c.TartufoTag}, + {Registry: PyPI, Name: "ruff", Indirect: &c.RuffVersion}, + {Registry: PyPI, Name: "mypy", Indirect: &c.MypyVersion}, + {Registry: PyPI, Name: "pytest", Indirect: &c.PytestVersion}, + {Registry: PyPI, Name: "pytest-mock", Indirect: &c.PytestMockVersion}, + {Registry: PyPI, Name: "pytest-cov", Indirect: &c.PytestCovVersion}, + {Registry: PyPI, Name: "Sphinx", Indirect: &c.SphinxVersion}, + {Registry: GitHub, Scope: "godaddy", Name: "tartufo", Indirect: &c.TartufoVersion}, } return nil diff --git a/scaffold/project_test.go b/scaffold/project_test.go index ca2da10..651bdd2 100644 --- a/scaffold/project_test.go +++ b/scaffold/project_test.go @@ -52,9 +52,6 @@ type ( SetupTools struct { PackageData map[string][]string `toml:"package-data"` } `toml:"setuptools"` - Black struct { - TargetVersion []string `toml:"target-version"` - } `toml:"black"` } `toml:"tool"` DepGroups struct { @@ -75,11 +72,11 @@ type ( ) func TestProjects(t *testing.T) { - handlerFactory := func(tmplt, version string) http.Handler { + handlerFactory := func(tmplt, specifier string) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { t.Helper() - body := fmt.Sprintf(tmplt, version) + body := fmt.Sprintf(tmplt, specifier) _, err := w.Write([]byte(body)) require.NoError(t, err) @@ -88,12 +85,11 @@ func TestProjects(t *testing.T) { mux := http.NewServeMux() - githubVersion := "v1.2.3" + githubTag := "v1.2.3" pypiVersion := "4.5.6" npmVersion := "7.8.9" - mypyVersion := "1.1" - mux.Handle("GET /{owner}/{repo}/releases/latest", handlerFactory(`{"tag_name": %q}`, githubVersion)) + mux.Handle("GET /{owner}/{repo}/releases/latest", handlerFactory(`{"tag_name": %q}`, githubTag)) mux.Handle("GET /{name}/json", handlerFactory(`{"info": {"version": %q}}`, pypiVersion)) npmHandler := handlerFactory(`{"dist-tags": {"latest": %q}}`, npmVersion) @@ -104,7 +100,6 @@ func TestProjects(t *testing.T) { mux.Handle("GET /@aws-cdk/assert", npmHandler) ts := httptest.NewServer(mux) - defer ts.Close() t.Run("GoProject", func(t *testing.T) { @@ -119,11 +114,11 @@ func TestProjects(t *testing.T) { defer func() { githubAPIURLPrefix = original }() cmd := GoProjectCmd{ - ModulePath: "module-path", - GoVersion: "1.24.5", - GolangcilintTag: "LATEST", - TartufoTag: "LATEST", - TimeoutSeconds: 5, + ModulePath: "module-path", + GoVersion: "1.24.5", + GolangcilintVersion: SemVer{}, + TartufoVersion: SemVer{}, + TimeoutSeconds: 5, } err = cmd.BeforeReset() @@ -146,7 +141,7 @@ func TestProjects(t *testing.T) { require.NoError(t, err) assert.Equal(t, "^"+cmd.GoVersion, workflow.Jobs["test-and-lint"].Steps[1].With["go-version"]) - assert.Equal(t, githubVersion, workflow.Jobs["test-and-lint"].Steps[len(workflow.Jobs["test-and-lint"].Steps)-1].With["version"]) + assert.Equal(t, githubTag, workflow.Jobs["test-and-lint"].Steps[len(workflow.Jobs["test-and-lint"].Steps)-1].With["version"]) contents, err = os.ReadFile(filepath.Clean(filepath.Join(tempDir, ".pre-commit-config.yaml"))) require.NoError(t, err) @@ -156,8 +151,8 @@ func TestProjects(t *testing.T) { err = yaml.Unmarshal(contents, &preCommitConfig) require.NoError(t, err) - assert.Equal(t, githubVersion, preCommitConfig.Repos[0].Rev) - assert.Equal(t, githubVersion, preCommitConfig.Repos[1].Rev) + assert.Equal(t, githubTag, preCommitConfig.Repos[0].Rev) + assert.Equal(t, githubTag, preCommitConfig.Repos[1].Rev) for _, hook := range preCommitConfig.Repos[0].Hooks { assert.True(t, strings.HasPrefix(hook.Id, "golangci-lint-")) @@ -198,17 +193,24 @@ func TestProjects(t *testing.T) { assert.Equal(t, "3", pythonVersion.Major) assert.Equal(t, "12", pythonVersion.Minor) + mypyVersion := SemVer{} + err = mypyVersion.UnmarshalText([]byte("1.2")) + require.NoError(t, err) + + assert.Equal(t, "1", mypyVersion.major) + assert.Equal(t, "2", mypyVersion.minor) + assert.Equal(t, "0", mypyVersion.bugfix) + assert.True(t, mypyVersion.Set()) + cmd := PythonProjectCmd{ ProjectName: "fs-walk", Description: "description", - BlackVersion: "LATEST", - Flake8Version: "LATEST", - TartufoTag: "LATEST", + TartufoVersion: SemVer{}, MypyVersion: mypyVersion, - PytestVersion: "LATEST", - PytestMockVersion: "LATEST", - PytestCovVersion: "LATEST", - SphinxVersion: "LATEST", + PytestVersion: SemVer{}, + PytestMockVersion: SemVer{}, + PytestCovVersion: SemVer{}, + SphinxVersion: SemVer{}, PythonVersion: pythonVersion, TimeoutSeconds: 5, } @@ -234,9 +236,8 @@ func TestProjects(t *testing.T) { err = yaml.Unmarshal(contents, &preCommitConfig) require.NoError(t, err) - assert.Equal(t, githubVersion, preCommitConfig.Repos[0].Rev) - assert.Equal(t, pypiVersion, preCommitConfig.Repos[1].Rev) - assert.Equal(t, githubVersion, preCommitConfig.Repos[3].Rev) + assert.Equal(t, "v"+pypiVersion, preCommitConfig.Repos[0].Rev, "the ruff-pre-commit repo should have the right rev field") + assert.Equal(t, githubTag, preCommitConfig.Repos[2].Rev, "the tartufo repo should have the right rev field") contents, err = os.ReadFile(filepath.Clean(filepath.Join(tempDir, "pyproject.toml"))) require.NoError(t, err) @@ -251,28 +252,23 @@ func TestProjects(t *testing.T) { assert.Equal(t, fmt.Sprintf("~=%s.0", cmd.PythonVersion.String()), pyProjectToml.Project.RequiresPython) assert.Equal(t, "py.typed", pyProjectToml.Tool.SetupTools.PackageData[dashLower(cmd.ProjectName)][0]) - assert.True(t, strings.HasPrefix(pyProjectToml.DepGroups.Linting[0], "black==")) - assert.Equal(t, githubVersion, strings.TrimPrefix(pyProjectToml.DepGroups.Linting[0], "black==")) + assert.Equal(t, mypyVersion.MajorMinor(), strings.TrimPrefix(pyProjectToml.DepGroups.Linting[1], "mypy~=")) - assert.True(t, strings.HasPrefix(pyProjectToml.DepGroups.Linting[1], "flake8==")) - assert.Equal(t, pypiVersion, strings.TrimPrefix(pyProjectToml.DepGroups.Linting[1], "flake8==")) - - assert.Equal(t, mypyVersion, strings.TrimPrefix(pyProjectToml.DepGroups.Linting[2], "mypy~=")) + pypiSemVer := &SemVer{} + err = pypiSemVer.SetFromString(pypiVersion) + require.NoError(t, err) - expected := strings.TrimSuffix(pypiVersion, ".6") + expected := pypiSemVer.MajorMinor() + assert.Equal(t, expected, strings.TrimPrefix(pyProjectToml.DepGroups.Linting[0], "ruff~=")) assert.Equal(t, expected, strings.TrimPrefix(pyProjectToml.DepGroups.Test[0], "pytest~=")) assert.Equal(t, expected, strings.TrimPrefix(pyProjectToml.DepGroups.Test[1], "pytest-mock~=")) assert.Equal(t, expected, strings.TrimPrefix(pyProjectToml.DepGroups.Test[2], "pytest-cov~=")) - assert.Equal(t, expected, strings.TrimPrefix(pyProjectToml.DepGroups.Docs[0], "sphinx~=")) - assert.Equal(t, "py"+cmd.PythonVersion.NumsOnly(), pyProjectToml.Tool.Black.TargetVersion[0]) - var contents1 []byte constantFiles := []string{ - ".flake8", ".gitignore", "mypy.ini", "tartufo.toml", @@ -341,20 +337,20 @@ func TestProjects(t *testing.T) { cmd := TsCdkProjectCmd{ ProjectName: "adhoc", - EslintVersion: "LATEST", - EslintJsVersion: "LATEST", - TypeScriptEslintVersion: "LATEST", - VitestVersion: "LATEST", - VitestCoverageV8Version: "LATEST", - AwsCdkCliVersion: "LATEST", - EsbuildVersion: "LATEST", - PrettierVersion: "LATEST", - TsxVersion: "LATEST", - TypeScriptVersion: "LATEST", - AwsCdkAssertVersion: "LATEST", - AwsCdkLibVersion: "LATEST", - ConstructsVersion: "LATEST", - YamlVersion: "LATEST", + EslintVersion: SemVer{}, + EslintJsVersion: SemVer{}, + TypeScriptEslintVersion: SemVer{}, + VitestVersion: SemVer{}, + VitestCoverageV8Version: SemVer{}, + AwsCdkCliVersion: SemVer{}, + EsbuildVersion: SemVer{}, + PrettierVersion: SemVer{}, + TsxVersion: SemVer{}, + TypeScriptVersion: SemVer{}, + AwsCdkAssertVersion: SemVer{}, + AwsCdkLibVersion: SemVer{}, + ConstructsVersion: SemVer{}, + YamlVersion: SemVer{}, NodejsVersion: nodejsVersion, TimeoutSeconds: 5, } diff --git a/tui/tui.go b/tui/tui.go index 6bc2e99..9e4750d 100644 --- a/tui/tui.go +++ b/tui/tui.go @@ -304,7 +304,7 @@ func InitialPythonModel(cmd *scaffold.PythonProjectCmd) pythonDeps { depItems := make([]depItem, len(vss)) for i := range vss { - *vss[i].Indirect = "LATEST" + vss[i].Indirect = &scaffold.SemVer{} ti = textinput.New() ti.Placeholder = "LATEST" From 6218f4f80cab13dd4d4cd5f40fd8a51ce2b6b24c Mon Sep 17 00:00:00 2001 From: kxue43 Date: Wed, 17 Dec 2025 13:33:34 -0500 Subject: [PATCH 2/2] fix: `toolkit-tui`. --- tui/tui.go | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/tui/tui.go b/tui/tui.go index 9e4750d..f4c5fc7 100644 --- a/tui/tui.go +++ b/tui/tui.go @@ -301,11 +301,9 @@ func InitialPythonModel(cmd *scaffold.PythonProjectCmd) pythonDeps { var ti textinput.Model vss := cmd.VersionSetters - depItems := make([]depItem, len(vss)) - - for i := range vss { - vss[i].Indirect = &scaffold.SemVer{} + depItems := make([]depItem, len(vss)-1) // The last versionSetter tartufo is not a depItem. + for i := range depItems { ti = textinput.New() ti.Placeholder = "LATEST" ti.CharLimit = 128 @@ -328,9 +326,9 @@ func InitialPythonModel(cmd *scaffold.PythonProjectCmd) pythonDeps { } grouping := [][]int{ - {0, 1, 2}, - {3, 4, 5}, - {6}, + {0, 1}, + {2, 3, 4}, + {5}, } for i, items := range grouping {