diff --git a/pkg/linter/defaults/defaults.go b/pkg/linter/defaults/defaults.go index 2986aa911..c784eb308 100644 --- a/pkg/linter/defaults/defaults.go +++ b/pkg/linter/defaults/defaults.go @@ -23,6 +23,7 @@ var DefaultLinters = []string{ "opt", "python/docs", "python/multiple", + "python/test", "srv", "setuidgid", "strip", diff --git a/pkg/linter/linter.go b/pkg/linter/linter.go index 50737962f..96f3db33b 100644 --- a/pkg/linter/linter.go +++ b/pkg/linter/linter.go @@ -119,6 +119,11 @@ var postLinterMap = map[string]postLinter{ FailOnError: false, Explain: "Split this package up into multiple packages and verify you are not improperly using pip install", }, + "python/test": postLinter{ + LinterFunc: pythonTestPostLinter, + FailOnError: false, + Explain: "Remove all test directories from the package", + }, } var isDevRegex = regexp.MustCompile("^dev/") @@ -364,7 +369,7 @@ func pythonDocsPostLinter(_ LinterContext, fsys fs.FS) error { for _, m := range packages { base := filepath.Base(m) if base == "doc" || base == "docs" { - return fmt.Errorf("Docs diretory encountered in Python directory") + return fmt.Errorf("Docs directory encountered in Python site-packages directory") } } @@ -427,6 +432,22 @@ func pythonMultiplePackagesPostLinter(_ LinterContext, fsys fs.FS) error { return nil } +func pythonTestPostLinter(_ LinterContext, fsys fs.FS) error { + packages, err := getPythonSitePackages(fsys) + if err != nil { + return err + } + + for _, m := range packages { + base := filepath.Base(m) + if base == "test" || base == "tests" { + return fmt.Errorf("Tests directory encountered in Python site-packages directory") + } + } + + return nil +} + // Checks if the linters in the given slice are known linters // Returns an empty slice if all linters are known, otherwise a slice with all the bad linters func CheckValidLinters(check []string) []string { diff --git a/pkg/linter/linter_test.go b/pkg/linter/linter_test.go index 2d55677c5..21be3310d 100644 --- a/pkg/linter/linter_test.go +++ b/pkg/linter/linter_test.go @@ -322,6 +322,53 @@ func Test_pythonMultiplePackagesLinter(t *testing.T) { assert.True(t, called) } +func Test_pythonTestLinter(t *testing.T) { + dir, err := os.MkdirTemp("", "melange.XXXXX") + defer os.RemoveAll(dir) + assert.NoError(t, err) + + cfg := config.Configuration{ + Package: config.Package{ + Name: "testpythontest", + Version: "4.2.0", + Epoch: 0, + Checks: checksOnly("python/test"), + }, + } + + // Base dir + pythonPathdir := filepath.Join(dir, "usr", "lib", "python3.14", "site-packages") + + linters := cfg.Package.Checks.GetLinters() + assert.Equal(t, linters, []string{"python/test"}) + + fsys := os.DirFS(dir) + lctx := NewLinterContext(cfg.Package.Name, fsys) + + // Make one "package" + packagedir := filepath.Join(pythonPathdir, "foo") + err = os.MkdirAll(packagedir, 0700) + assert.NoError(t, err) + + // One package should not trip it + called := false + assert.NoError(t, lctx.LintPackageFs(fsys, func(err error) { + called = true + }, linters)) + assert.False(t, called) + + // Create docs + docsdir := filepath.Join(pythonPathdir, "test") + err = os.MkdirAll(docsdir, 0700) + assert.NoError(t, err) + + // This should trip + assert.NoError(t, lctx.LintPackageFs(fsys, func(err error) { + called = true + }, linters)) + assert.True(t, called) +} + func Test_srvLinter(t *testing.T) { dir, err := os.MkdirTemp("", "melange.XXXXX") defer os.RemoveAll(dir)