Skip to content

Consolidate duplicate Python helpers between hook executor and framework service #7570

@wbreza

Description

@wbreza

Summary

The multi-language hooks feature (PR #7451) introduced pkg/tools/language/python_executor.go which contains Python venv/pip orchestration logic that partially duplicates existing code in pkg/project/framework_service_python.go. Both files independently import pkg/tools/python/ for low-level operations but reimplement the orchestration layer around those calls.

This issue tracks extracting shared helpers into pkg/tools/python/ where both consumers already depend, eliminating ~80-100 lines of duplication.

Duplications Identified

Venv Naming ({baseName}_env)

  • Executor: venvNameForDir(projectDir string) string (python_executor.go:408-416)
  • Framework: getVenvName(serviceConfig *ServiceConfig) string (framework_service_python.go:185-192)
  • Action: Extract to python.VenvNameForDir(projectDir string) string
  • Character-for-character identical logic with different parameter types.

Venv Ensure (stat → create)

  • Executor: ensureVenv() — stat, is-dir check, errors.Is, create (python_executor.go:184-219)
  • Framework: Inline in Restore() — stat, os.IsNotExist, create (framework_service_python.go:62-79)
  • Action: Extract to python.Cli.EnsureVirtualEnv(ctx, workingDir, name, env) error
  • Use executor's stricter implementation (has directory type check, modern errors.Is).

Dep Install Dispatch (requirements.txt vs pyproject.toml)

  • Executor: installDeps() — switch on depFile (python_executor.go:223-251)
  • Framework: Inline in Restore() — if/else on depFile (framework_service_python.go:82-96)
  • Action: Extract to python.Cli.InstallDependencies(ctx, dir, venvName, depFile, env) error
  • Detection stays separate (framework checks one dir; executor walks up). Only dispatch is shared.

Python Command Resolution (py/python/python3)

  • Executor: resolvePythonCmd(runner) string (python_executor.go:313-332)
  • Framework: Uses python.Cli.checkPath() — private (python.go:151-173)
  • Action: Export existing checkPath() as python.Cli.ResolveCommand() (string, error)
  • Same resolution order (Windows: py→python; Unix: python3).

Venv Directory Layout (Scripts/bin)

  • Executor: resolvePythonPath() — builds venv python binary path (python_executor.go:297-307)
  • Framework: Inline in Run() — builds venv activation script path (python.go:130-136)
  • Action: Extract to python.VenvPythonPath(venvDir) string + python.VenvActivateCmd(venvDir) string

What Stays in the Executor (NOT consolidated)

These are hook-specific features the framework service doesn't need:

  • detectExistingVenv() — checks VIRTUAL_ENV env var, .venv, venv dirs
  • DiscoverProjectFile() — walk-up directory search from script location
  • hasPyvenvCfg() — venv validation heuristic
  • Direct python binary invocation (vs shell activation)

Dependency Graph

\
pkg/tools/python/ ← both already import this (leaf package)
↑ ↑
| |
language/ project/
(hook executor) (framework service)
\\

No circular dependency risk — python/ imports neither language/ nor project/.

Estimated Impact

  • ~80-100 lines removed across both consumers
  • ~60 lines added to pkg/tools/python/ (mostly moved, not new)
  • pythonTools interface simplified to 3 methods

Related

Metadata

Metadata

Assignees

Labels

enhancementNew feature or improvement

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions