jupyterlab-mlflow 0.4.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of jupyterlab-mlflow might be problematic. Click here for more details.
- jupyterlab_mlflow/__init__.py +63 -0
- jupyterlab_mlflow/_version.py +6 -0
- jupyterlab_mlflow/post_install.py +44 -0
- jupyterlab_mlflow/schema/plugin.json +17 -0
- jupyterlab_mlflow/serverextension/__init__.py +69 -0
- jupyterlab_mlflow/serverextension/handlers.py +570 -0
- jupyterlab_mlflow/serverextension/mlflow_server.py +214 -0
- jupyterlab_mlflow-0.4.1.data/data/etc/jupyter/jupyter_server_config.d/jupyterlab_mlflow.json +8 -0
- jupyterlab_mlflow-0.4.1.data/data/share/jupyter/labextensions/jupyterlab-mlflow/install.json +12 -0
- jupyterlab_mlflow-0.4.1.data/data/share/jupyter/labextensions/jupyterlab-mlflow/package.json +103 -0
- jupyterlab_mlflow-0.4.1.data/data/share/jupyter/labextensions/jupyterlab-mlflow/schema/plugin.json +17 -0
- jupyterlab_mlflow-0.4.1.data/data/share/jupyter/labextensions/jupyterlab-mlflow/schemas/jupyterlab-mlflow/package.json.orig +98 -0
- jupyterlab_mlflow-0.4.1.data/data/share/jupyter/labextensions/jupyterlab-mlflow/schemas/jupyterlab-mlflow/plugin.json +17 -0
- jupyterlab_mlflow-0.4.1.data/data/share/jupyter/labextensions/jupyterlab-mlflow/static/218.47b1285b67dde3db8969.js +1 -0
- jupyterlab_mlflow-0.4.1.data/data/share/jupyter/labextensions/jupyterlab-mlflow/static/665.f3ea36ea04224fd9c2f3.js +1 -0
- jupyterlab_mlflow-0.4.1.data/data/share/jupyter/labextensions/jupyterlab-mlflow/static/remoteEntry.121dc9414dda869fb1a6.js +1 -0
- jupyterlab_mlflow-0.4.1.data/data/share/jupyter/labextensions/jupyterlab-mlflow/static/style.js +4 -0
- jupyterlab_mlflow-0.4.1.data/data/share/jupyter/labextensions/jupyterlab-mlflow/static/third-party-licenses.json +16 -0
- jupyterlab_mlflow-0.4.1.dist-info/METADATA +273 -0
- jupyterlab_mlflow-0.4.1.dist-info/RECORD +23 -0
- jupyterlab_mlflow-0.4.1.dist-info/WHEEL +4 -0
- jupyterlab_mlflow-0.4.1.dist-info/entry_points.txt +2 -0
- jupyterlab_mlflow-0.4.1.dist-info/licenses/LICENSE +30 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""
|
|
2
|
+
JupyterLab MLflow Extension
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import subprocess
|
|
6
|
+
import sys
|
|
7
|
+
import os
|
|
8
|
+
|
|
9
|
+
from ._version import __version__
|
|
10
|
+
|
|
11
|
+
# Auto-enable server extension on import (if not already enabled)
|
|
12
|
+
def _auto_enable_server_extension():
|
|
13
|
+
"""Attempt to auto-enable the server extension"""
|
|
14
|
+
try:
|
|
15
|
+
# Check if already enabled by trying to import the config
|
|
16
|
+
from jupyter_server.services.config.manager import ConfigManager
|
|
17
|
+
cm = ConfigManager()
|
|
18
|
+
|
|
19
|
+
# Try to enable the extension
|
|
20
|
+
result = subprocess.run(
|
|
21
|
+
[sys.executable, "-m", "jupyter", "server", "extension", "enable",
|
|
22
|
+
"jupyterlab_mlflow.serverextension", "--sys-prefix"],
|
|
23
|
+
capture_output=True,
|
|
24
|
+
text=True,
|
|
25
|
+
timeout=5
|
|
26
|
+
)
|
|
27
|
+
if result.returncode != 0:
|
|
28
|
+
# Try without --sys-prefix
|
|
29
|
+
subprocess.run(
|
|
30
|
+
[sys.executable, "-m", "jupyter", "server", "extension", "enable",
|
|
31
|
+
"jupyterlab_mlflow.serverextension"],
|
|
32
|
+
capture_output=True,
|
|
33
|
+
text=True,
|
|
34
|
+
timeout=5
|
|
35
|
+
)
|
|
36
|
+
except Exception:
|
|
37
|
+
# Silently fail - don't break installation if this doesn't work
|
|
38
|
+
pass
|
|
39
|
+
|
|
40
|
+
# Only auto-enable if we're being imported in a Jupyter context
|
|
41
|
+
# (not during build/installation)
|
|
42
|
+
if not os.environ.get('JUPYTERLAB_MLFLOW_SKIP_AUTO_ENABLE'):
|
|
43
|
+
try:
|
|
44
|
+
_auto_enable_server_extension()
|
|
45
|
+
except Exception:
|
|
46
|
+
pass
|
|
47
|
+
|
|
48
|
+
def _jupyter_labextension_paths():
|
|
49
|
+
"""Called by Jupyter Lab Server to detect if it is a valid labextension and
|
|
50
|
+
to install the widget
|
|
51
|
+
|
|
52
|
+
Returns
|
|
53
|
+
=======
|
|
54
|
+
src: Source directory name to copy files from. The JupyterLab builder outputs
|
|
55
|
+
generated files into this directory and Jupyter Lab copies from this
|
|
56
|
+
directory during widget installation
|
|
57
|
+
dest: Destination directory name to install to
|
|
58
|
+
"""
|
|
59
|
+
return [{
|
|
60
|
+
'src': 'labextension',
|
|
61
|
+
'dest': 'jupyterlab-mlflow'
|
|
62
|
+
}]
|
|
63
|
+
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Post-install hook to auto-enable the server extension
|
|
3
|
+
"""
|
|
4
|
+
import subprocess
|
|
5
|
+
import sys
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def enable_server_extension():
|
|
9
|
+
"""Enable the server extension after installation"""
|
|
10
|
+
try:
|
|
11
|
+
# Try to enable the extension
|
|
12
|
+
result = subprocess.run(
|
|
13
|
+
[sys.executable, "-m", "jupyter", "server", "extension", "enable",
|
|
14
|
+
"jupyterlab_mlflow.serverextension", "--sys-prefix"],
|
|
15
|
+
capture_output=True,
|
|
16
|
+
text=True,
|
|
17
|
+
timeout=10
|
|
18
|
+
)
|
|
19
|
+
if result.returncode == 0:
|
|
20
|
+
print("✅ Server extension enabled successfully")
|
|
21
|
+
return True
|
|
22
|
+
else:
|
|
23
|
+
# Try without --sys-prefix
|
|
24
|
+
result = subprocess.run(
|
|
25
|
+
[sys.executable, "-m", "jupyter", "server", "extension", "enable",
|
|
26
|
+
"jupyterlab_mlflow.serverextension"],
|
|
27
|
+
capture_output=True,
|
|
28
|
+
text=True,
|
|
29
|
+
timeout=10
|
|
30
|
+
)
|
|
31
|
+
if result.returncode == 0:
|
|
32
|
+
print("✅ Server extension enabled successfully")
|
|
33
|
+
return True
|
|
34
|
+
else:
|
|
35
|
+
print(f"⚠️ Could not enable server extension: {result.stderr}")
|
|
36
|
+
return False
|
|
37
|
+
except Exception as e:
|
|
38
|
+
print(f"⚠️ Error enabling server extension: {e}")
|
|
39
|
+
return False
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
if __name__ == "__main__":
|
|
43
|
+
enable_server_extension()
|
|
44
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"jupyter.lab.setting-icon": "mlflow:icon",
|
|
3
|
+
"jupyter.lab.setting-icon-label": "MLflow",
|
|
4
|
+
"title": "MLflow",
|
|
5
|
+
"description": "MLflow extension settings",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"properties": {
|
|
8
|
+
"mlflowTrackingUri": {
|
|
9
|
+
"type": "string",
|
|
10
|
+
"title": "MLflow Tracking URI",
|
|
11
|
+
"description": "URI of the MLflow tracking server (e.g., http://localhost:5000). Leave empty to use MLFLOW_TRACKING_URI environment variable.",
|
|
12
|
+
"default": ""
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"additionalProperties": false
|
|
16
|
+
}
|
|
17
|
+
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""
|
|
2
|
+
JupyterLab MLflow Server Extension
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
from .handlers import setup_handlers
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
# Track if extension has been loaded to avoid duplicate registration
|
|
11
|
+
_extension_loaded = False
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _jupyter_server_extension_points():
|
|
15
|
+
"""
|
|
16
|
+
Returns a list of dictionaries with metadata about
|
|
17
|
+
the server extension points.
|
|
18
|
+
"""
|
|
19
|
+
return [{
|
|
20
|
+
"module": "jupyterlab_mlflow.serverextension"
|
|
21
|
+
}]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _load_jupyter_server_extension(server_app):
|
|
25
|
+
"""Registers the API handler to receive HTTP requests from the frontend extension.
|
|
26
|
+
|
|
27
|
+
Parameters
|
|
28
|
+
----------
|
|
29
|
+
server_app: jupyter_server.serverapp.ServerApp
|
|
30
|
+
Jupyter Server application instance
|
|
31
|
+
"""
|
|
32
|
+
global _extension_loaded
|
|
33
|
+
|
|
34
|
+
# Prevent duplicate registration
|
|
35
|
+
if _extension_loaded:
|
|
36
|
+
server_app.log.warning("jupyterlab-mlflow: Extension already loaded, skipping duplicate registration")
|
|
37
|
+
return
|
|
38
|
+
|
|
39
|
+
try:
|
|
40
|
+
setup_handlers(server_app.web_app)
|
|
41
|
+
_extension_loaded = True
|
|
42
|
+
|
|
43
|
+
# Log success
|
|
44
|
+
success_msg = "✅ Registered jupyterlab-mlflow server extension"
|
|
45
|
+
server_app.log.info(success_msg)
|
|
46
|
+
logger.info(success_msg)
|
|
47
|
+
|
|
48
|
+
# Log startup verification details
|
|
49
|
+
base_url = server_app.web_app.settings.get("base_url", "/")
|
|
50
|
+
verification_msg = f"✅ jupyterlab-mlflow: Server extension loaded successfully with base_url: {base_url}"
|
|
51
|
+
server_app.log.info(verification_msg)
|
|
52
|
+
logger.info(verification_msg)
|
|
53
|
+
|
|
54
|
+
except Exception as e:
|
|
55
|
+
error_msg = f"❌ Failed to register jupyterlab-mlflow server extension: {e}"
|
|
56
|
+
server_app.log.error(error_msg)
|
|
57
|
+
logger.error(error_msg, exc_info=True)
|
|
58
|
+
# Don't raise - allow JupyterLab to continue loading even if extension fails
|
|
59
|
+
# This prevents the entire server from failing due to extension issues
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
# For Jupyter Server 2.x compatibility
|
|
63
|
+
def _jupyter_server_extension_paths():
|
|
64
|
+
"""
|
|
65
|
+
Returns a list of server extension paths for Jupyter Server 2.x.
|
|
66
|
+
"""
|
|
67
|
+
return [{
|
|
68
|
+
"module": "jupyterlab_mlflow.serverextension"
|
|
69
|
+
}]
|