Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,7 @@ wheels/

# tmp files
.tmp

# Node.js dependencies (downloaded during build)
node_modules/
package-lock.json
63 changes: 63 additions & 0 deletions build_hooks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
"""Simple build hook to run npm install for Pyodide bundling."""

import subprocess
import sys
from pathlib import Path
from typing import Any

from hatchling.builders.hooks.plugin.interface import BuildHookInterface


class NpmInstallBuildHook(BuildHookInterface):
"""Build hook that runs npm install to download Pyodide for bundling."""

PLUGIN_NAME = "custom"

def initialize(self, version: str, build_data: dict[str, Any]) -> None:
"""Run npm install to download Pyodide files for bundling."""
build_dir = Path(self.root)
package_json = build_dir / "package.json"
node_modules = build_dir / "node_modules"

# Check if package.json exists
if not package_json.exists():
print("⚠ No package.json found - skipping npm install")
return

# Check if node_modules already exists and is populated
pyodide_dir = node_modules / "pyodide"
if pyodide_dir.exists() and (pyodide_dir / "pyodide.js").exists():
print("βœ“ Pyodide already installed in node_modules")
return

print("πŸ“¦ Running npm install to download Pyodide for bundling...")

try:
# Run npm install
result = subprocess.run(
["npm", "install"],
cwd=build_dir,
capture_output=True,
text=True,
timeout=300, # 5 minute timeout
)

if result.returncode == 0:
print("βœ“ npm install completed successfully")
# Verify Pyodide was installed
if (pyodide_dir / "pyodide.js").exists():
print("βœ“ Pyodide files ready for bundling")
else:
print("⚠ npm install succeeded but Pyodide files not found")
else:
print(f"βœ— npm install failed with exit code {result.returncode}")
if result.stderr:
print(f"Error output: {result.stderr}")

except subprocess.TimeoutExpired:
print("βœ— npm install timed out after 5 minutes")
except FileNotFoundError:
print("βœ— npm not found - please ensure Node.js and npm are installed")
sys.exit(1)
except Exception as e:
print(f"βœ— npm install failed: {e}")
15 changes: 15 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "mip-mcp-pyodide-deps",
"version": "1.0.0",
"description": "Node.js dependencies for MIP-MCP Pyodide execution",
"private": true,
"scripts": {
"postinstall": "echo 'βœ“ Pyodide installed successfully for bundling'"
},
"dependencies": {
"pyodide": "^0.27.7"
},
"engines": {
"node": ">=18.0.0"
}
}
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ indent-style = "space"
[tool.hatch.build.targets.wheel]
packages = ["src/mip_mcp"]

[tool.hatch.build.targets.wheel.hooks.custom]
path = "build_hooks.py"

[tool.hatch.build.targets.wheel.shared-data]
"node_modules/pyodide/pyodide.js" = "mip_mcp/pyodide/pyodide.js"
"node_modules/pyodide/pyodide.asm.js" = "mip_mcp/pyodide/pyodide.asm.js"
Expand Down
Loading