diff --git a/scaffold/.go/.github/workflows/test-and-lint.yaml.tmplt b/scaffold/.go/.github/workflows/test-and-lint.yaml.tmplt index 3e638bb..834e4ad 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: "{% .GolangcilintVersion %}" + version: "{% .GolangcilintTag %}" diff --git a/scaffold/.go/.pre-commit-config.yaml.tmplt b/scaffold/.go/.pre-commit-config.yaml.tmplt index 37ef290..2eae8e8 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: "{% .GolangcilintVersion %}" + rev: "{% .GolangcilintTag %}" hooks: - id: golangci-lint-config-verify - id: golangci-lint-fmt - id: golangci-lint-full - repo: https://github.com/godaddy/tartufo - rev: "{% .TartufoVersion %}" + rev: "{% .TartufoTag %}" hooks: - id: tartufo diff --git a/scaffold/.python/.github/workflows/publish-docs.yaml.tmplt b/scaffold/.python/.github/workflows/publish-docs.yaml.tmplt index ea077e3..5ae44c9 100644 --- a/scaffold/.python/.github/workflows/publish-docs.yaml.tmplt +++ b/scaffold/.python/.github/workflows/publish-docs.yaml.tmplt @@ -6,8 +6,8 @@ on: paths: - "docs/**" - "src/**.py" - - "poetry.lock" - "pyproject.toml" + - "uv.lock" workflow_dispatch: @@ -31,34 +31,23 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - - name: Get poetry from cache - id: poetry-cache - uses: actions/cache@v4 + - name: Set up Python + uses: actions/setup-python@v6 with: - path: ${{ github.workspace }}/pipx/venvs/poetry/** - key: default-branch-poetry-cache + python-version-file: "pyproject.toml" - - name: Install poetry if cache misses - if: ${{ steps.poetry-cache.outputs.cache-hit != 'true' }} - run: PIPX_HOME=$GITHUB_WORKSPACE/pipx pipx install poetry - - - name: Add poetry executable to PATH - run: echo "$GITHUB_WORKSPACE/pipx/venvs/poetry/bin" >> $GITHUB_PATH - - - name: Set up Python and cache poetry install - uses: actions/setup-python@v5 + - name: Install uv + uses: astral-sh/setup-uv@v7 with: - python-version: '{% .PythonVersion %}' - cache: 'poetry' + enable-cache: true - - name: Install dependencies with poetry - run: poetry install + - name: Install the project + run: uv sync --locked - name: Make HTML - run: poetry run make clean && poetry run make html - working-directory: ./docs + run: uv run --directory=docs sphinx-build -M html . _build - name: Setup Pages uses: actions/configure-pages@v4 diff --git a/scaffold/.python/.github/workflows/python-lint-on-pr.yaml.tmplt b/scaffold/.python/.github/workflows/python-lint-on-pr.yaml.tmplt index b765ebb..6ed453a 100644 --- a/scaffold/.python/.github/workflows/python-lint-on-pr.yaml.tmplt +++ b/scaffold/.python/.github/workflows/python-lint-on-pr.yaml.tmplt @@ -8,7 +8,7 @@ on: - 'src/**.py' - 'tests/**.py' - 'pyproject.toml' - - 'poetry.lock' + - 'uv.lock' workflow_call: @@ -20,21 +20,21 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: - python-version: "{% .PythonVersion %}" + python-version-file: "pyproject.toml" - name: Install pre-commit run: pip install pre-commit - name: Cache pre-commit environments - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.cache/pre-commit key: pre-commit-3|${{ env.pythonLocation }}|${{ hashFiles('.pre-commit-config.yaml') }} - - name: Run pre-commit hooks + - name: Run pre-commit hooks run: pre-commit run --show-diff-on-failure --color=never --all-files --hook-stage=pre-commit diff --git a/scaffold/.python/.github/workflows/unit-test.yaml.tmplt b/scaffold/.python/.github/workflows/unit-test.yaml.tmplt index 702244c..e714281 100644 --- a/scaffold/.python/.github/workflows/unit-test.yaml.tmplt +++ b/scaffold/.python/.github/workflows/unit-test.yaml.tmplt @@ -7,13 +7,15 @@ on: paths: - 'src/**.py' - 'tests/**' - - 'poetry.lock' + - 'pyproject.toml' + - 'uv.lock' pull_request: paths: - 'src/**.py' - 'tests/**' - - 'poetry.lock' + - 'pyproject.toml' + - 'uv.lock' workflow_call: @@ -29,30 +31,20 @@ jobs: steps: - name: Checkout repo - uses: actions/checkout@v4 + uses: actions/checkout@v5 - - name: Get poetry from cache - id: poetry-cache - uses: actions/cache@v4 + - name: Set up Python + uses: actions/setup-python@v6 with: - path: ${{ github.workspace }}/pipx/venvs/poetry/** - key: default-branch-poetry-cache + python-version-file: "pyproject.toml" - - name: Install poetry if cache misses - if: ${{ steps.poetry-cache.outputs.cache-hit != 'true' }} - run: PIPX_HOME=$GITHUB_WORKSPACE/pipx pipx install poetry - - - name: Add poetry executable to PATH - run: echo "$GITHUB_WORKSPACE/pipx/venvs/poetry/bin" >> $GITHUB_PATH - - - name: Set up Python and cache poetry install - uses: actions/setup-python@v5 + - name: Install uv + uses: astral-sh/setup-uv@v7 with: - python-version: '{% .PythonVersion %}' - cache: 'poetry' + enable-cache: true - - name: Install dependencies with poetry - run: poetry install + - name: Install the project + run: uv sync --locked --no-group docs - name: Run unit test - run: poetry run pytest + run: uv run pytest diff --git a/scaffold/.python/.gitignore.tmplt b/scaffold/.python/.gitignore.tmplt index 9e3d278..2263134 100644 --- a/scaffold/.python/.gitignore.tmplt +++ b/scaffold/.python/.gitignore.tmplt @@ -1,12 +1,9 @@ .DS_Store -.python-version **/*.whl **/*.tar.gz /docs/node_modules /docs/_build -/poetry.toml src/*.egg-info /adhoc*.py __pycache__ /.coverage -/poetry.toml diff --git a/scaffold/.python/.pre-commit-config.yaml.tmplt b/scaffold/.python/.pre-commit-config.yaml.tmplt index cae5966..1a2fef8 100644 --- a/scaffold/.python/.pre-commit-config.yaml.tmplt +++ b/scaffold/.python/.pre-commit-config.yaml.tmplt @@ -3,7 +3,6 @@ repos: rev: "{% .BlackVersion %}" hooks: - id: black - language_version: python{% .PythonVersion %} - repo: https://github.com/PyCQA/flake8 rev: "{% .Flake8Version %}" @@ -11,20 +10,19 @@ repos: - id: flake8 - repo: https://github.com/kxue43/shell-cmd-on-change - rev: "1.2.0" + rev: "2.0.0" hooks: - id: shell-cmd-on-change - name: poetry-install + name: uv-sync args: - - "--paths" - - "poetry.lock" - - "--command" - - "poetry sync" + - "-Ppyproject.toml" + - "-Puv.lock" + - "uv sync" stages: [post-merge] always_run: true verbose: true - repo: https://github.com/godaddy/tartufo - rev: "{% .TartufoVersion %}" + rev: "{% .TartufoTag %}" hooks: - id: tartufo diff --git a/scaffold/.python/poetry.toml.tmplt b/scaffold/.python/poetry.toml.tmplt deleted file mode 100644 index ab1033b..0000000 --- a/scaffold/.python/poetry.toml.tmplt +++ /dev/null @@ -1,2 +0,0 @@ -[virtualenvs] -in-project = true diff --git a/scaffold/.python/pyproject.toml.tmplt b/scaffold/.python/pyproject.toml.tmplt index a313895..9c90b0c 100644 --- a/scaffold/.python/pyproject.toml.tmplt +++ b/scaffold/.python/pyproject.toml.tmplt @@ -1,23 +1,66 @@ [project] name = "{% .ProjectName %}" + version = "0.1.0" + authors = [ { name = "Ke Xue", email = "xueke.kent@gmail.com" }, ] + description = "{% .Description %}" + classifiers = [ "Programming Language :: Python :: 3", "Operating System :: OS Independent", ] -requires-python = "~{% .PythonVersion %}" + +requires-python = "~={% .PythonVersion %}.0" + dependencies = [] +[tool.uv] +default-groups = [ + "linting", + "test", + "docs", +] + +[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 %}", +] + +test = [ + "pytest~={% .PytestVersion %}", + "pytest-mock~={% .PytestMockVersion %}", + "pytest-cov~={% .PytestCovVersion %}", +] + +docs = [ + "sphinx~={% .SphinxVersion %}", + "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" + [build-system] requires = ["setuptools>=67", "wheel"] + build-backend = "setuptools.build_meta" [tool.setuptools] zip-safe = false + include-package-data = true [tool.setuptools.packages.find] @@ -25,48 +68,3 @@ where = ["src"] [tool.setuptools.package-data] {% .ProjectName | DashLower %} = ["py.typed"] - -[tool.poetry] -packages = [{ include = "**/*", from = "src" }] - -[tool.poetry.dependencies] -python = "~{% .PythonVersion %}" - -[tool.poetry.group.develop] -optional = false - -[tool.poetry.group.develop.dependencies] -ipykernel = "^{% .IPyKernelVersion %}" - -[tool.poetry.group.linting] -optional = false - -[tool.poetry.group.linting.dependencies] -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 %}" - -[tool.poetry.group.test] -optional = false - -[tool.poetry.group.test.dependencies] -pytest = "^{% .PytestVersion %}" -pytest-mock = "^{% .PytestMockVersion %}" -pytest-cov = "^{% .PytestCovVersion %}" - -[tool.poetry.group.docs] -optional = false - -[tool.poetry.group.docs.dependencies] -sphinx = "^{% .SphinxVersion %}" -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/.python/tartufo.toml.tmplt b/scaffold/.python/tartufo.toml.tmplt index 6a01afc..4b24708 100644 --- a/scaffold/.python/tartufo.toml.tmplt +++ b/scaffold/.python/tartufo.toml.tmplt @@ -4,7 +4,7 @@ regex = true entropy = true exclude-path-patterns = [ - {path-pattern = 'poetry\.lock$', reason = 'Lock file with lots of digests'}, + {path-pattern = 'uv\.lock$', reason = 'Lock file with lots of digests'}, {path-pattern = 'pyproject\.toml$', reason = 'Standard Python project config file'}, {path-pattern = 'tartufo\.toml$', reason = 'Tartufo config file'}, ] diff --git a/scaffold/project.go b/scaffold/project.go index 5ac9502..6df6ef4 100644 --- a/scaffold/project.go +++ b/scaffold/project.go @@ -23,53 +23,52 @@ 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."` - GolangcilintVersion string `name:"golangci-lint-version" default:"LATEST" help:"Will appear in .pre-commit-config.yaml and GitHub Actions workflow."` - TartufoVersion string `name:"tartufo-version" default:"LATEST" help:"Will appear in .pre-commit-config.yaml."` - VersionSetters []VersionSetter - 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."` + 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."` } 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:"Will appear in .pre-commit-config.yaml and pyproject.toml."` - Flake8Version string `name:"flake8-version" default:"LATEST" help:"Will appear in .pre-commit-config.yaml and pyproject.toml."` - TartufoVersion string `name:"tartufo-version" default:"LATEST" help:"Will appear in .pre-commit-config.yaml."` - IPyKernelVersion string `name:"ipykernel-version" default:"LATEST" help:"Will appear in pyproject.toml."` - MypyVersion string `name:"mypy-version" default:"LATEST" help:"Will appear in pyproject.toml."` - PytestVersion string `name:"pytest-version" default:"LATEST" help:"Will appear in pyproject.toml."` - PytestMockVersion string `name:"pytest-mock-version" default:"LATEST" help:"Will appear in pyproject.toml."` - PytestCovVersion string `name:"pytest-cov-version" default:"LATEST" help:"Will appear in pyproject.toml."` - SphinxVersion string `name:"sphinx-cov-version" default:"LATEST" help:"Will appear in pyproject.toml."` - PythonVersion PythonVersion `name:"python-version" required:"" help:"Python interpreter version. Only accept major and minor version, i.e. the 3.Y format."` - VersionSetters []VersionSetter - TimeoutSeconds int `name:"timeout-seconds" default:"1" help:"Timeout scaffolding after this many seconds."` + 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."` + 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."` } 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."` - NodejsVersion NodejsVersion `name:"nodejs-version" required:"" help:"Only accept major and minor version, i.e. the X.Y format."` - VersionSetters []VersionSetter - TimeoutSeconds int `name:"timeout-seconds" default:"1" help:"Timeout scaffolding after this many seconds."` + 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."` + 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."` } WriteHook func(io.Writer) error @@ -87,10 +86,11 @@ type ( Registry byte VersionSetter struct { - Indirect *string - Scope string - Name string - Registry Registry + Indirect *string + Scope string + Name string + Registry Registry + MajorMinorOnly bool } setterFunc func(context.Context) error @@ -119,6 +119,8 @@ var ( pypiURLPrefix = "https://pypi.org/pypi" tmpltExt = ".tmplt" + + versionRegex = regexp.MustCompile(`^(?:v)?(\d+\.\d+)(?:\.\d+)?$`) ) func (pv *PythonVersion) UnmarshalText(text []byte) error { @@ -383,6 +385,15 @@ func (vs VersionSetter) Func(ctx context.Context) (err error) { } } + 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] + } + return nil } @@ -424,8 +435,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.GolangcilintVersion}, - {Registry: GitHub, Scope: "godaddy", Name: "tartufo", Indirect: &c.TartufoVersion}, + {Registry: GitHub, Scope: "golangci", Name: "golangci-lint", Indirect: &c.GolangcilintTag}, + {Registry: GitHub, Scope: "godaddy", Name: "tartufo", Indirect: &c.TartufoTag}, } return nil @@ -460,15 +471,14 @@ func (c *GoProjectCmd) Run() (err error) { func (c *PythonProjectCmd) BeforeReset() error { c.VersionSetters = []VersionSetter{ - {Registry: PyPI, Name: "ipykernel", Indirect: &c.IPyKernelVersion}, {Registry: GitHub, Scope: "psf", Name: "black", Indirect: &c.BlackVersion}, {Registry: PyPI, Name: "flake8", Indirect: &c.Flake8Version}, - {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}, + {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}, } return nil diff --git a/scaffold/project_test.go b/scaffold/project_test.go index 00dbe85..ca2da10 100644 --- a/scaffold/project_test.go +++ b/scaffold/project_test.go @@ -36,8 +36,7 @@ type ( Repo string `yaml:"repo"` Rev string `yaml:"rev"` Hooks []struct { - Id string `yaml:"id"` - LanguageVersion string `yaml:"language_version"` + Id string `yaml:"id"` } `yaml:"hooks"` } `yaml:"repos"` } @@ -53,18 +52,16 @@ type ( SetupTools struct { PackageData map[string][]string `toml:"package-data"` } `toml:"setuptools"` - Poetry struct { - Group map[string]struct { - Dependencies map[string]string `toml:"dependencies"` - } `toml:"group"` - Dependencies struct { - Python string `toml:"python"` - } `toml:"dependencies"` - } `toml:"poetry"` Black struct { TargetVersion []string `toml:"target-version"` } `toml:"black"` } `toml:"tool"` + + DepGroups struct { + Linting []string `toml:"linting"` + Test []string `toml:"test"` + Docs []string `toml:"docs"` + } `toml:"dependency-groups"` } PackageJson struct { @@ -94,6 +91,7 @@ func TestProjects(t *testing.T) { githubVersion := "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 /{name}/json", handlerFactory(`{"info": {"version": %q}}`, pypiVersion)) @@ -121,11 +119,11 @@ func TestProjects(t *testing.T) { defer func() { githubAPIURLPrefix = original }() cmd := GoProjectCmd{ - ModulePath: "module-path", - GoVersion: "1.24.5", - GolangcilintVersion: "LATEST", - TartufoVersion: "LATEST", - TimeoutSeconds: 5, + ModulePath: "module-path", + GoVersion: "1.24.5", + GolangcilintTag: "LATEST", + TartufoTag: "LATEST", + TimeoutSeconds: 5, } err = cmd.BeforeReset() @@ -205,9 +203,8 @@ func TestProjects(t *testing.T) { Description: "description", BlackVersion: "LATEST", Flake8Version: "LATEST", - TartufoVersion: "LATEST", - IPyKernelVersion: "LATEST", - MypyVersion: "do-not-query", + TartufoTag: "LATEST", + MypyVersion: mypyVersion, PytestVersion: "LATEST", PytestMockVersion: "LATEST", PytestCovVersion: "LATEST", @@ -227,30 +224,8 @@ func TestProjects(t *testing.T) { err = cmd.Run() require.NoError(t, err) - workflowFiles := []struct { - name string - job string - index int - }{ - {"publish-docs.yaml", "publish", 4}, - {"python-lint-on-pr.yaml", "lint", 1}, - {"unit-test.yaml", "unit-test", 4}, - } - var contents []byte - var workflow Workflow - - for _, file := range workflowFiles { - contents, err = os.ReadFile(filepath.Clean(filepath.Join(tempDir, ".github", "workflows", file.name))) - require.NoError(t, err) - - err = yaml.Unmarshal(contents, &workflow) - require.NoError(t, err) - - assert.Equal(t, cmd.PythonVersion.String(), workflow.Jobs[file.job].Steps[file.index].With["python-version"]) - } - contents, err = os.ReadFile(filepath.Clean(filepath.Join(tempDir, ".pre-commit-config.yaml"))) require.NoError(t, err) @@ -263,8 +238,6 @@ func TestProjects(t *testing.T) { assert.Equal(t, pypiVersion, preCommitConfig.Repos[1].Rev) assert.Equal(t, githubVersion, preCommitConfig.Repos[3].Rev) - assert.Equal(t, "python"+cmd.PythonVersion.String(), preCommitConfig.Repos[0].Hooks[0].LanguageVersion) - contents, err = os.ReadFile(filepath.Clean(filepath.Join(tempDir, "pyproject.toml"))) require.NoError(t, err) @@ -275,17 +248,25 @@ func TestProjects(t *testing.T) { assert.Equal(t, cmd.ProjectName, pyProjectToml.Project.Name) assert.Equal(t, cmd.Description, pyProjectToml.Project.Description) - assert.Equal(t, "~"+cmd.PythonVersion.String(), pyProjectToml.Project.RequiresPython) + 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.Equal(t, "~"+cmd.PythonVersion.String(), pyProjectToml.Tool.Poetry.Dependencies.Python) - assert.Equal(t, "^"+pypiVersion, pyProjectToml.Tool.Poetry.Group["develop"].Dependencies["ipykernel"]) - assert.Equal(t, githubVersion, pyProjectToml.Tool.Poetry.Group["linting"].Dependencies["black"]) - assert.Equal(t, pypiVersion, pyProjectToml.Tool.Poetry.Group["linting"].Dependencies["flake8"]) - assert.Equal(t, "^do-not-query", pyProjectToml.Tool.Poetry.Group["linting"].Dependencies["mypy"]) - assert.Equal(t, "^"+pypiVersion, pyProjectToml.Tool.Poetry.Group["test"].Dependencies["pytest"]) - assert.Equal(t, "^"+pypiVersion, pyProjectToml.Tool.Poetry.Group["test"].Dependencies["pytest-mock"]) - assert.Equal(t, "^"+pypiVersion, pyProjectToml.Tool.Poetry.Group["test"].Dependencies["pytest-cov"]) - assert.Equal(t, "^"+pypiVersion, pyProjectToml.Tool.Poetry.Group["docs"].Dependencies["sphinx"]) + + assert.True(t, strings.HasPrefix(pyProjectToml.DepGroups.Linting[0], "black==")) + assert.Equal(t, githubVersion, strings.TrimPrefix(pyProjectToml.DepGroups.Linting[0], "black==")) + + 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~=")) + + expected := strings.TrimSuffix(pypiVersion, ".6") + + 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 @@ -294,7 +275,6 @@ func TestProjects(t *testing.T) { ".flake8", ".gitignore", "mypy.ini", - "poetry.toml", "tartufo.toml", filepath.Join("docs", "_static", "custom.css"), filepath.Join("docs", ".air.toml"), diff --git a/tui/tui.go b/tui/tui.go index 7b94fa1..6bc2e99 100644 --- a/tui/tui.go +++ b/tui/tui.go @@ -291,13 +291,12 @@ func InitialPythonModel(cmd *scaffold.PythonProjectCmd) pythonDeps { groups := make([]depsGroup, 4) groups[0] = depsGroup{ - name: "develop", + name: "linting", highlighted: true, } - groups[1] = depsGroup{name: "linting"} - groups[2] = depsGroup{name: "test"} - groups[3] = depsGroup{name: "docs"} + groups[1] = depsGroup{name: "test"} + groups[2] = depsGroup{name: "docs"} var ti textinput.Model @@ -329,10 +328,9 @@ func InitialPythonModel(cmd *scaffold.PythonProjectCmd) pythonDeps { } grouping := [][]int{ - {0}, - {1, 2, 3}, - {4, 5, 6}, - {7, 8}, + {0, 1, 2}, + {3, 4, 5}, + {6}, } for i, items := range grouping {