Skip to content

Commit

Permalink
perf: cache the result of "pyenv which python"
Browse files Browse the repository at this point in the history
It's expensive to keep invoking `pyenv which python` for equivalent `.python-version` contents.
So we cache the result based on the content of `.python-version` file.

Signed-off-by: Jack Cherng <jfcherng@gmail.com>
  • Loading branch information
jfcherng committed Nov 4, 2024
1 parent cad7617 commit de78643
Showing 1 changed file with 26 additions and 6 deletions.
32 changes: 26 additions & 6 deletions plugin/virtual_env/venv_finder.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,12 @@ class PyenvVenvFinder(BaseVenvFinder):
@see https://github.com/pyenv/pyenv
"""

result_caches: dict[int, Pep405VenvInfo | None] = {}
"""
It's expensive to keep invoking `pyenv which python` for equivalent `.python-version` contents.
So we cache the result based on the content of `.python-version` file.
"""

@classmethod
def can_support(cls, project_dir: Path) -> bool:
try:
Expand All @@ -248,13 +254,27 @@ def can_support(cls, project_dir: Path) -> bool:
return False

def find_venv_(self) -> Pep405VenvInfo | None:
if not (output := run_shell_command("pyenv which python", cwd=self.project_dir)):
return None
python_executable, _, _ = output
def _work() -> Pep405VenvInfo | None:
if not (output := run_shell_command("pyenv which python", cwd=self.project_dir)):
return None
python_executable, _, _ = output

if not python_executable:
return None
return Pep405VenvInfo.from_python_executable(python_executable)
if not python_executable:
return None
return Pep405VenvInfo.from_python_executable(python_executable)

pyver_file_sig = self.calculate_pyver_file_signature(self.project_dir / ".python-version")
if pyver_file_sig not in self.result_caches:
self.result_caches[pyver_file_sig] = _work()
return self.result_caches[pyver_file_sig]

@staticmethod
def calculate_pyver_file_signature(file: Path) -> int:
content = b""
for line in file.open("rb"):
if (line := line.strip()) and not line.startswith(b"#"):
content += line + b"\n"
return hash(content)


class RyeVenvFinder(BaseVenvFinder):
Expand Down

0 comments on commit de78643

Please sign in to comment.