Skip to content

Commit 3b564ba

Browse files
committed
fix: hash venv name
1 parent d72c7ba commit 3b564ba

File tree

2 files changed

+34
-9
lines changed

2 files changed

+34
-9
lines changed

DEEPNOTE_KERNEL_IMPLEMENTATION.md

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ This implementation adds automatic kernel selection and startup for `.deepnote`
3535
**Key Methods:**
3636
- `getVenvInterpreter(deepnoteFileUri)`: Gets the venv Python interpreter for a specific file
3737
- `ensureInstalled(interpreter, deepnoteFileUri)`: Creates venv, installs toolkit and ipykernel, and registers kernel spec
38-
- `getVenvHash(deepnoteFileUri)`: Creates a unique hash for kernel naming
38+
- `getVenvHash(deepnoteFileUri)`: Creates a unique hash for both kernel naming and venv directory paths
3939
- `getDisplayName(deepnoteFileUri)`: Gets a friendly display name for the kernel
4040

4141
#### 3. **Deepnote Server Starter** (`src/kernels/deepnote/deepnoteServerStarter.node.ts`)
@@ -155,7 +155,7 @@ User runs cell → Executes on Deepnote kernel
155155
- **Wheel URL**: `https://deepnote-staging-runtime-artifactory.s3.amazonaws.com/deepnote-toolkit-packages/0.2.30.post20/deepnote_toolkit-0.2.30.post20-py3-none-any.whl`
156156
- **Default Port**: `8888` (will find next available if occupied)
157157
- **Notebook Type**: `deepnote`
158-
- **Venv Location**: `~/.vscode/extensions/storage/deepnote-venvs/<file-path-hash>/`
158+
- **Venv Location**: `~/.vscode/extensions/storage/deepnote-venvs/<hashed-path>/` (e.g., `venv_a1b2c3d4`)
159159
- **Server Provider ID**: `deepnote-server`
160160
- **Kernel Spec Name**: `deepnote-venv-<file-path-hash>` (registered via ipykernel to point to venv Python)
161161
- **Kernel Display Name**: `Deepnote (<notebook-filename>)`
@@ -302,6 +302,19 @@ Instead of creating custom kernel specs, the implementation:
302302
4. Uses this existing spec when creating the kernel connection metadata
303303
5. This ensures compatibility with the Deepnote server's kernel configuration
304304

305+
### Virtual Environment Path Handling
306+
307+
The implementation uses a robust hashing approach for virtual environment directory names:
308+
309+
1. **Path Hashing**: Uses `getVenvHash()` to create short, unique identifiers from file paths
310+
2. **Hash Algorithm**: Implements a djb2-style hash function for better distribution
311+
3. **Format**: Generates identifiers like `venv_a1b2c3d4` (max 16 characters)
312+
4. **Benefits**:
313+
- Avoids Windows MAX_PATH (260 character) limitations
314+
- Prevents directory structure leakage into extension storage
315+
- Provides consistent naming for both venv directories and kernel specs
316+
- Reduces collision risk with better hash distribution
317+
305318
## Troubleshooting & Key Fixes
306319

307320
### Issue 1: "Unable to get resolved server information"

src/kernels/deepnote/deepnoteToolkitInstaller.node.ts

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ export class DeepnoteToolkitInstaller implements IDeepnoteToolkitInstaller {
2929
) {}
3030

3131
private getVenvPath(deepnoteFileUri: Uri): Uri {
32-
// Create a unique venv name based on the file path
33-
// Use a simple hash approach - replace special chars with underscores
34-
const safePath = deepnoteFileUri.fsPath.replace(/[^a-zA-Z0-9]/g, '_');
35-
return Uri.joinPath(this.context.globalStorageUri, 'deepnote-venvs', safePath);
32+
// Create a unique venv name based on the file path using a hash
33+
// This avoids Windows MAX_PATH issues and prevents directory structure leakage
34+
const hash = this.getVenvHash(deepnoteFileUri);
35+
return Uri.joinPath(this.context.globalStorageUri, 'deepnote-venvs', hash);
3636
}
3737

3838
public async getVenvInterpreter(deepnoteFileUri: Uri): Promise<PythonEnvironment | undefined> {
@@ -240,9 +240,21 @@ export class DeepnoteToolkitInstaller implements IDeepnoteToolkitInstaller {
240240
}
241241

242242
private getVenvHash(deepnoteFileUri: Uri): string {
243-
// Create a short hash from the file path for kernel naming
244-
const safePath = deepnoteFileUri.fsPath.replace(/[^a-zA-Z0-9]/g, '_');
245-
return safePath.substring(0, 16); // Limit length
243+
// Create a short hash from the file path for kernel naming and venv directory
244+
// This provides better uniqueness and prevents directory structure leakage
245+
const path = deepnoteFileUri.fsPath;
246+
247+
// Use a simple hash function for better distribution
248+
let hash = 0;
249+
for (let i = 0; i < path.length; i++) {
250+
const char = path.charCodeAt(i);
251+
hash = (hash << 5) - hash + char;
252+
hash = hash & hash; // Convert to 32-bit integer
253+
}
254+
255+
// Convert to positive hex string and limit length
256+
const hashStr = Math.abs(hash).toString(16);
257+
return `venv_${hashStr}`.substring(0, 16);
246258
}
247259

248260
private getDisplayName(deepnoteFileUri: Uri): string {

0 commit comments

Comments
 (0)