Jupyter Server File ID
Jupyter Server File ID is an extension for Jupyter Server that provides an implementation of the File ID service. Its primary purpose is to allow developers to consistently track the path of files within a running Jupyter Server environment over their lifetime, even if the files are moved or renamed. The current version is 0.9.3, with updates released periodically to maintain compatibility and add features.
Warnings
- gotcha The `jupyter-server-fileid` extension must be properly enabled within your Jupyter Server. If the frontend components of a Jupyter extension are visible but not functional, always verify the server extension status.
- gotcha Users migrating from older Jupyter Notebook server configurations (`jupyter_notebook_config.py`) to the newer Jupyter Server architecture (`jupyter_server_config.py`) may encounter issues. Ensure that server-specific configurations for extensions like `jupyter-server-fileid` are placed in the correct `jupyter_server_config.py` file.
- gotcha The `LocalFileIdManager` instance is typically accessed through `serverapp.settings['file_id_manager']` from the `ServerApp` instance, which is available within the context of a running Jupyter Server. Attempting to directly import and instantiate `LocalFileIdManager` outside of this context may lead to incorrect behavior or require extensive manual setup of its dependencies.
Install
-
pip install jupyter_server_fileid
Imports
- LocalFileIdManager
from jupyter_server.base.handlers import JupyterHandler # LocalFileIdManager is typically accessed via serverapp.settings['file_id_manager'] # Direct import for type hinting or advanced use might be: from jupyter_server_fileid.manager import LocalFileIdManager
Quickstart
import os
import tempfile
from unittest.mock import MagicMock
# Simulate a minimal ServerApp and its settings for demonstration
class MockServerApp:
def __init__(self):
self.settings = {}
# In a real Jupyter Server environment, serverapp would be the active application instance
serverapp = MockServerApp()
# --- In a real Jupyter Server, jupyter_server_fileid would populate this setting ---
# For this quickstart, we'll manually set up a mock manager
# In a live environment, you would ensure the extension is enabled.
# Example: serverapp.settings["file_id_manager"] = LocalFileIdManager(parent=serverapp)
# Mocking LocalFileIdManager for a runnable quickstart without a full Jupyter Server setup
class MockLocalFileIdManager:
def __init__(self):
self._files = {}
self._next_id = 1
def index(self, path):
abs_path = os.path.abspath(path)
for fid, stored_path in self._files.items():
if stored_path == abs_path:
return fid
new_id = str(self._next_id)
self._files[new_id] = abs_path
self._next_id += 1
return new_id
def get_path(self, file_id):
return self._files.get(file_id)
def update_path(self, file_id, new_path):
if file_id in self._files:
self._files[file_id] = os.path.abspath(new_path)
return True
return False
serverapp.settings['file_id_manager'] = MockLocalFileIdManager()
# ----------------------------------------------------------------------------------
# Access the File ID manager from the server settings
fim = serverapp.settings['file_id_manager']
# Create a temporary file to demonstrate tracking
with tempfile.TemporaryDirectory() as tmpdir:
original_path = os.path.join(tmpdir, 'my_notebook.ipynb')
with open(original_path, 'w') as f:
f.write('# My Notebook')
# 1. Index the file to get a unique File ID
file_id = fim.index(original_path)
print(f"Original path: {original_path}")
print(f"Generated File ID: {file_id}")
# 2. Get the current path using the File ID
current_path = fim.get_path(file_id)
print(f"Current path retrieved by ID: {current_path}")
# 3. Simulate moving the file
new_path = os.path.join(tmpdir, 'moved_notebook.ipynb')
os.rename(original_path, new_path)
print(f"File moved to: {new_path}")
# In a real scenario, the File ID service would detect and update its internal mapping.
# For this mock, we'll manually update for demonstration purposes if `update_path` existed.
# A real LocalFileIdManager would likely have filesystem watchers or hooks.
fim.update_path(file_id, new_path) # Simulating the internal update
# 4. Get the path again after the move - it should reflect the new location
updated_path = fim.get_path(file_id)
print(f"Updated path retrieved by ID: {updated_path}")
assert updated_path == os.path.abspath(new_path)
print("File ID successfully tracked the moved file.")