From 33211f48840cddbe937c2527700999a5e432bf00 Mon Sep 17 00:00:00 2001 From: AlexMili Date: Thu, 30 May 2024 17:18:57 +0200 Subject: [PATCH] Add feature to scan directory for virtual env --- README.md | 40 +++++++++++++++++++++++++++++++++++++++- isvirtual/cli.py | 20 ++++++++++++++++++-- isvirtual/main.py | 20 ++++++++++++++++++++ pyproject.toml | 2 +- 4 files changed, 78 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index f5c1a26..da5c739 100644 --- a/README.md +++ b/README.md @@ -83,12 +83,50 @@ if __name__ == "__main__": print("404 Not Found") ``` +You can recursively scan a directory to get all virtual environments in it: +```python +from isvirtual import scan_dir + +if __name__ == "__main__": + scanned = scan_dir("/some/dir/path") + if len(scanned) > 0: + print(f"Found {len(scanned)} virtual env(s)") + else: + print("No virtual env found") +``` + ## CLI ```console -$ isvirtual +$ isvirtual --help +Usage: isvirtual [OPTIONS] COMMAND [ARGS]... + +╭─ Options ──────────────────────────────────────────────────────────────────────────────╮ +│ --help Show this message and exit. │ +╰────────────────────────────────────────────────────────────────────────────────────────╯ +╭─ Commands ─────────────────────────────────────────────────────────────────────────────╮ +│ check Check if you are currently in a virtual env │ +│ info If the given directory is linked to a virtual env, show its info │ +│ scan Scan the given directory recursively to find all virtual environment in it │ +╰────────────────────────────────────────────────────────────────────────────────────────╯ +``` + +Check if a virtual env is currently activated (support conda): +```console +$ isvirtual check Yes ``` +Show info of current directory's virtual env info: +```console +$ isviritual info . +home=/usr/local/opt/python@3.10/bin +include-system-site-packages=false +version=3.10.14 +path=/Users/MyUserName/MyDir/.venv +source=venv +``` +Also display with the `source` key if the virtual env has been created through `venv`, `virtualenv`, `poetry` and `pipenv`. + # License This project is licensed under the terms of the MIT license. diff --git a/isvirtual/cli.py b/isvirtual/cli.py index 9bc7583..73d59bb 100644 --- a/isvirtual/cli.py +++ b/isvirtual/cli.py @@ -1,8 +1,8 @@ import typer +from sty import fg from typing_extensions import Annotated -from sty import fg -from isvirtual import check_dir, is_virtual_env +from isvirtual import check_dir, is_virtual_env, scan_dir app = typer.Typer(add_completion=False) @@ -29,3 +29,19 @@ def info( print(f"{fg.blue}{k}={fg.green}{v}") else: print(f"{fg.red}Virtual environment not found") + +@app.command( + help="Scan the given directory recursively to find all virtual environment in it" +) +def scan( + path: Annotated[ + str, + typer.Argument(), + ] = ".", +) -> None: + envs = scan_dir(path) + + for env in envs: + print(env) + + print(f"\n{fg.blue}Found {len(envs)} virtual environment(s)") diff --git a/isvirtual/main.py b/isvirtual/main.py index 8e18dd9..5f6b5c6 100644 --- a/isvirtual/main.py +++ b/isvirtual/main.py @@ -8,6 +8,7 @@ import sys from contextlib import suppress from pathlib import Path +import subprocess from platformdirs import user_cache_path @@ -192,6 +193,25 @@ def check_dir(path: str | Path) -> dict: return config +def scan_dir(path: str) -> list[str]: + output = subprocess.check_output( + f"find {path} -name activate -type f 2>/dev/null", shell=True + ) + envs = output.decode("utf-8") + validated_envs = [] + for line in envs.split("\n"): + if len(line) > 0: + cpath = Path(line) + if ( + (cpath.parent.parent / "bin").exists() is True + and (cpath.parent.parent / "include").exists() is True + and (cpath.parent.parent / "lib").exists() is True + and (cpath.parent.parent / "pyvenv.cfg").exists() is True + ): + validated_envs.append(cpath.parent.parent) + return validated_envs + + def _encode(string: str, encodings: list[str] | None = None) -> bytes: if isinstance(string, bytes): return string diff --git a/pyproject.toml b/pyproject.toml index cb47dd7..8365b1a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,7 +26,7 @@ classifiers = [ "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", ] -keywords = ["virtual", "env", "venv", "virtualenv", "environment", "poetry", "pipenv", "pdm"] +keywords = ["virtual", "env", "venv", "virtualenv", "environment", "poetry", "pipenv", "pdm", "hatch"] dependencies = ["platformdirs", "typer", "sty"] [project.urls]