Buckets:
ktongue/docker_container / .vscode-server /extensions /ms-python.vscode-python-envs-1.22.0 /.github /skills /python-manager-discovery /SKILL.md
| name: python-manager-discovery | |
| description: Environment manager-specific discovery patterns and known issues. Use when working on or reviewing environment discovery code for conda, poetry, pipenv, pyenv, or venv. | |
| argument-hint: 'manager name (e.g., poetry, conda, pyenv)' | |
| user-invocable: false | |
| # Environment Manager Discovery Patterns | |
| This skill documents manager-specific discovery patterns, environment variable precedence, and known issues. | |
| ## Manager Quick Reference | |
| | Manager | Config Files | Cache Location | Key Env Vars | | |
| | ------- | ---------------------------------------------- | ------------------------ | --------------------------------------------------- | | |
| | Poetry | `poetry.toml`, `pyproject.toml`, `config.toml` | Platform-specific | `POETRY_VIRTUALENVS_IN_PROJECT`, `POETRY_CACHE_DIR` | | |
| | Pipenv | `Pipfile`, `Pipfile.lock` | XDG or WORKON_HOME | `WORKON_HOME`, `XDG_DATA_HOME` | | |
| | Pyenv | `.python-version`, `versions/` | `~/.pyenv/` or pyenv-win | `PYENV_ROOT`, `PYENV_VERSION` | | |
| | Conda | `environment.yml`, `conda-meta/` | Registries + paths | `CONDA_PREFIX`, `CONDA_DEFAULT_ENV` | | |
| | venv | `pyvenv.cfg` | In-project | None | | |
| --- | |
| ## Poetry | |
| ### Discovery Locations | |
| **Virtualenvs cache (default):** | |
| - Windows: `%LOCALAPPDATA%\pypoetry\Cache\virtualenvs` | |
| - macOS: `~/Library/Caches/pypoetry/virtualenvs` | |
| - Linux: `~/.cache/pypoetry/virtualenvs` | |
| **In-project (when enabled):** | |
| - `.venv/` in project root | |
| ### Config Precedence (highest to lowest) | |
| 1. Local config: `poetry.toml` in project root | |
| 2. Environment variables: `POETRY_VIRTUALENVS_*` | |
| 3. Global config: `~/.config/pypoetry/config.toml` | |
| ### Known Issues | |
| | Issue | Description | Fix | | |
| | ------------------------- | ----------------------------------------------- | -------------------------------- | | |
| | `{cache-dir}` placeholder | Not resolved in paths from config | Resolve placeholder before use | | |
| | Wrong default path | Windows/macOS differ from Linux | Use platform-specific defaults | | |
| | In-project detection | `POETRY_VIRTUALENVS_IN_PROJECT` must be checked | Check env var first, then config | | |
| ### Code Pattern | |
| ```typescript | |
| async function getPoetryVirtualenvsPath(): Promise<string> { | |
| // 1. Check environment variable first | |
| const envVar = process.env.POETRY_VIRTUALENVS_PATH; | |
| if (envVar) return envVar; | |
| // 2. Check local poetry.toml | |
| const localConfig = await readPoetryToml(projectRoot); | |
| if (localConfig?.virtualenvs?.path) { | |
| return resolvePoetryPath(localConfig.virtualenvs.path); | |
| } | |
| // 3. Use platform-specific default | |
| return getDefaultPoetryCache(); | |
| } | |
| function resolvePoetryPath(configPath: string): string { | |
| // Handle {cache-dir} placeholder | |
| if (configPath.includes('{cache-dir}')) { | |
| const cacheDir = getDefaultPoetryCache(); | |
| return configPath.replace('{cache-dir}', cacheDir); | |
| } | |
| return configPath; | |
| } | |
| ``` | |
| --- | |
| ## Pipenv | |
| ### Discovery Locations | |
| **Default:** | |
| - Linux: `~/.local/share/virtualenvs/` (XDG_DATA_HOME) | |
| - macOS: `~/.local/share/virtualenvs/` | |
| - Windows: `~\.virtualenvs\` | |
| **When WORKON_HOME is set:** | |
| - Use `$WORKON_HOME/` directly | |
| ### Environment Variables | |
| | Var | Purpose | | |
| | ------------------------ | ---------------------------- | | |
| | `WORKON_HOME` | Override virtualenv location | | |
| | `XDG_DATA_HOME` | Base for Linux default | | |
| | `PIPENV_VENV_IN_PROJECT` | Create `.venv/` in project | | |
| ### Known Issues | |
| | Issue | Description | Fix | | |
| | ----------------------------- | ------------------- | ---------------------------- | | |
| | Missing WORKON_HOME support | Env var not checked | Read env var before defaults | | |
| | Missing XDG_DATA_HOME support | Not used on Linux | Check XDG spec | | |
| ### Code Pattern | |
| ```typescript | |
| function getPipenvVirtualenvsPath(): string { | |
| // Check WORKON_HOME first | |
| if (process.env.WORKON_HOME) { | |
| return process.env.WORKON_HOME; | |
| } | |
| // Check XDG_DATA_HOME on Linux | |
| if (process.platform === 'linux') { | |
| const xdgData = process.env.XDG_DATA_HOME || path.join(os.homedir(), '.local', 'share'); | |
| return path.join(xdgData, 'virtualenvs'); | |
| } | |
| // Windows/macOS defaults | |
| return path.join(os.homedir(), '.virtualenvs'); | |
| } | |
| ``` | |
| --- | |
| ## PyEnv | |
| ### Discovery Locations | |
| **Unix:** | |
| - `~/.pyenv/versions/` (default) | |
| - `$PYENV_ROOT/versions/` (if PYENV_ROOT set) | |
| **Windows (pyenv-win):** | |
| - `%USERPROFILE%\.pyenv\pyenv-win\versions\` | |
| - Different directory structure than Unix! | |
| ### Key Differences: Unix vs Windows | |
| | Aspect | Unix | Windows (pyenv-win) | | |
| | ------- | ----------------- | --------------------------------------- | | |
| | Command | `pyenv` | `pyenv.bat` | | |
| | Root | `~/.pyenv/` | `%USERPROFILE%\.pyenv\pyenv-win\` | | |
| | Shims | `~/.pyenv/shims/` | `%USERPROFILE%\.pyenv\pyenv-win\shims\` | | |
| ### Known Issues | |
| | Issue | Description | Fix | | |
| | ---------------------------------- | ------------------------------------------ | ---------------------------------- | | |
| | path.normalize() vs path.resolve() | Windows drive letter missing | Use `path.resolve()` on both sides | | |
| | Wrong command on Windows | Looking for `pyenv` instead of `pyenv.bat` | Check for `.bat` extension | | |
| ### Code Pattern | |
| ```typescript | |
| function getPyenvRoot(): string { | |
| if (process.env.PYENV_ROOT) { | |
| return process.env.PYENV_ROOT; | |
| } | |
| if (process.platform === 'win32') { | |
| // pyenv-win uses different structure | |
| return path.join(os.homedir(), '.pyenv', 'pyenv-win'); | |
| } | |
| return path.join(os.homedir(), '.pyenv'); | |
| } | |
| function getPyenvVersionsPath(): string { | |
| const root = getPyenvRoot(); | |
| return path.join(root, 'versions'); | |
| } | |
| // Use path.resolve() for comparisons! | |
| function comparePyenvPaths(pathA: string, pathB: string): boolean { | |
| return path.resolve(pathA) === path.resolve(pathB); | |
| } | |
| ``` | |
| --- | |
| ## Conda | |
| ### Discovery Locations | |
| **Environment locations:** | |
| - Base install `envs/` directory | |
| - `~/.conda/envs/` | |
| - Paths in `~/.condarc` `envs_dirs` | |
| **Windows Registry:** | |
| - `HKCU\Software\Python\ContinuumAnalytics\` | |
| - `HKLM\SOFTWARE\Python\ContinuumAnalytics\` | |
| ### Shell Activation | |
| | Shell | Activation Command | | |
| | ---------- | -------------------------------------- | | |
| | bash, zsh | `source activate envname` | | |
| | fish | `conda activate envname` (NOT source!) | | |
| | PowerShell | `conda activate envname` | | |
| | cmd | `activate.bat envname` | | |
| ### Known Issues | |
| | Issue | Description | Fix | | |
| | --------------------- | ----------------------- | -------------------------- | | |
| | Fish shell activation | Uses bash-style command | Use fish-compatible syntax | | |
| | Registry paths | May be stale/invalid | Verify paths exist | | |
| | Base vs named envs | Different activation | Check if activating base | | |
| ### Code Pattern | |
| ```typescript | |
| function getCondaActivationCommand(shell: ShellType, envName: string): string { | |
| switch (shell) { | |
| case 'fish': | |
| // Fish uses different syntax! | |
| return `conda activate ${envName}`; | |
| case 'cmd': | |
| return `activate.bat ${envName}`; | |
| case 'powershell': | |
| return `conda activate ${envName}`; | |
| default: | |
| // bash, zsh | |
| return `source activate ${envName}`; | |
| } | |
| } | |
| ``` | |
| --- | |
| ## venv | |
| ### Discovery | |
| **Identification:** | |
| - Look for `pyvenv.cfg` file in directory | |
| - Contains `home` and optionally `version` keys | |
| ### Version Extraction Priority | |
| 1. `version` field in `pyvenv.cfg` | |
| 2. Parse from `home` path (e.g., `Python311`) | |
| 3. Spawn Python executable (last resort) | |
| ### Code Pattern | |
| ```typescript | |
| async function getVenvVersion(venvPath: string): Promise<string | undefined> { | |
| const cfgPath = path.join(venvPath, 'pyvenv.cfg'); | |
| try { | |
| const content = await fs.readFile(cfgPath, 'utf-8'); | |
| const lines = content.split('\n'); | |
| for (const line of lines) { | |
| const [key, value] = line.split('=').map((s) => s.trim()); | |
| if (key === 'version') { | |
| return value; | |
| } | |
| } | |
| // Fall back to parsing home path | |
| const homeLine = lines.find((l) => l.startsWith('home')); | |
| if (homeLine) { | |
| const home = homeLine.split('=')[1].trim(); | |
| const match = home.match(/(\d+)\.(\d+)/); | |
| if (match) { | |
| return `${match[1]}.${match[2]}`; | |
| } | |
| } | |
| } catch { | |
| // Config file not found or unreadable | |
| } | |
| return undefined; | |
| } | |
| ``` | |
| --- | |
| ## PET Server (Native Finder) | |
| ### JSON-RPC Communication | |
| The PET server is a Rust-based locator that communicates via JSON-RPC over stdio. | |
| ### Known Issues | |
| | Issue | Description | Fix | | |
| | ------------------- | -------------------------------- | ----------------------------- | | |
| | No timeout | JSON-RPC can hang forever | Add Promise.race with timeout | | |
| | Silent spawn errors | Extension continues without envs | Surface spawn errors to user | | |
| | Resource leaks | Worker pool not cleaned up | Dispose on deactivation | | |
| | Type guard missing | Response types not validated | Add runtime type checks | | |
| | Cache key collision | Paths normalize to same key | Use consistent normalization | | |
| ### Code Pattern | |
| ```typescript | |
| async function fetchFromPET<T>(method: string, params: unknown): Promise<T> { | |
| const timeout = 30000; // 30 seconds | |
| const result = await Promise.race([ | |
| this.client.request(method, params), | |
| new Promise<never>((_, reject) => setTimeout(() => reject(new Error('PET server timeout')), timeout)), | |
| ]); | |
| // Validate response type | |
| if (!isValidResponse<T>(result)) { | |
| throw new Error(`Invalid response from PET: ${JSON.stringify(result)}`); | |
| } | |
| return result; | |
| } | |
| ``` | |
Xet Storage Details
- Size:
- 10.7 kB
- Xet hash:
- f9d33030a0bcde74d8e55e377fa7f3a7c4ffc4b60a772de57c4f64e2336cfd4c
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.