Skip to content

Commit

Permalink
bug fix: support env / status without pip (#992) (#999)
Browse files Browse the repository at this point in the history
  • Loading branch information
dmadisetti committed Mar 25, 2024
1 parent d12191f commit ca1a808
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 124 deletions.
131 changes: 11 additions & 120 deletions marimo/_cli/envinfo.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
# Copyright 2024 Marimo. All rights reserved.
from __future__ import annotations

import json
import platform
import subprocess
import sys
from typing import Optional, Union
from typing import Union

from marimo import __version__
from marimo._utils.health import (
get_chrome_version,
get_node_version,
get_required_modules_list,
)


def get_system_info() -> dict[str, Union[str, dict[str, str]]]:
Expand All @@ -21,123 +23,12 @@ def get_system_info() -> dict[str, Union[str, dict[str, str]]]:
}

binaries = {
"Chrome": _get_chrome_version() or "--",
"Node": _get_node_version() or "--",
# Check chrome specifically if invoked from cli, this value could be
# back-filled in frontend
"Browser": get_chrome_version() or "--",
"Node": get_node_version() or "--",
}

requirements = _get_pip_list()
requirements = get_required_modules_list()

return {**info, "Binaries": binaries, "Requirements": requirements}


def _get_node_version() -> Optional[str]:
try:
process = subprocess.Popen(
["node", "--version"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
)
stdout, stderr = process.communicate()
if stderr:
return None
return stdout.strip().split()[-1]
except FileNotFoundError:
return None


def _get_pip_list() -> dict[str, str]:
allowlist = [
"click",
"importlib_resources",
"jedi",
"markdown",
"pymdown-extensions",
"pygments",
"tomlkit",
"uvicorn",
"starlette",
"websocket",
"typing_extensions",
"black",
]
try:
result = subprocess.run(
[
sys.executable,
"-m",
"pip",
"list",
"--format=json",
"--disable-pip-version-check",
],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
packages = json.loads(result.stdout)
return {
package["name"]: package["version"]
for package in packages
if package["name"] in allowlist
}
except FileNotFoundError:
return {}


def _get_chrome_version() -> Optional[str]:
def get_chrome_version_windows() -> Optional[str]:
process = subprocess.Popen(
[
"reg",
"query",
"HKEY_CURRENT_USER\\Software\\Google\\Chrome\\BLBeacon",
"/v",
"version",
],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
)
stdout, stderr = process.communicate()
if stderr:
return None
return stdout.strip().split()[-1]

def get_chrome_version_mac() -> Optional[str]:
process = subprocess.Popen(
[
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
"--version",
],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
)
stdout, stderr = process.communicate()
if stderr:
return None
return stdout.strip().split()[-1]

def get_chrome_version_linux() -> Optional[str]:
process = subprocess.Popen(
["google-chrome", "--version"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
)
stdout, stderr = process.communicate()
if stderr:
return None
return stdout.strip().split()[-1]

try:
if sys.platform.startswith("win32"):
return get_chrome_version_windows()
elif sys.platform.startswith("darwin"):
return get_chrome_version_mac()
elif sys.platform.startswith("linux"):
return get_chrome_version_linux()
else:
return None
except FileNotFoundError:
return None
3 changes: 3 additions & 0 deletions marimo/_server/api/endpoints/health.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from marimo import __version__, _loggers
from marimo._server.api.deps import AppState
from marimo._server.router import APIRouter
from marimo._utils.health import get_node_version, get_required_modules_list

LOGGER = _loggers.marimo_logger()

Expand Down Expand Up @@ -34,6 +35,8 @@ async def status(request: Request) -> JSONResponse:
"mode": app_state.mode,
"sessions": len(app_state.session_manager.sessions),
"version": __version__,
"requirements": get_required_modules_list(),
"node_version": get_node_version(),
"lsp_running": app_state.session_manager.lsp_server.is_running(),
}
)
112 changes: 112 additions & 0 deletions marimo/_utils/health.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# Copyright 2024 Marimo. All rights reserved.
from __future__ import annotations

import subprocess
import sys
from typing import Optional


# Stub for missing modules
class _DefaultModule:
__version__ = "missing"


def get_node_version() -> Optional[str]:
try:
process = subprocess.Popen(
["node", "--version"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
)
stdout, stderr = process.communicate()
if stderr:
return None
return stdout.strip().split()[-1]
except FileNotFoundError:
return None


def get_required_modules_list() -> dict[str, str]:
allowlist = [
"click",
"importlib_resources",
"jedi",
"markdown",
"pymdown-extensions",
"pygments",
"tomlkit",
"uvicorn",
"starlette",
"websocket",
"typing_extensions",
"black",
]
# Consider listing all installed modules and their versions
# Submodules and private modules are can be filtered with:
# if not ("." in m or m.startswith("_")):
return {
module: getattr(
sys.modules.get(module, _DefaultModule), "__version__", "--"
)
for module in allowlist
}


def get_chrome_version() -> Optional[str]:
def get_chrome_version_windows() -> Optional[str]:
process = subprocess.Popen(
[
"reg",
"query",
"HKEY_CURRENT_USER\\Software\\Google\\Chrome\\BLBeacon",
"/v",
"version",
],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
)
stdout, stderr = process.communicate()
if stderr:
return None
return stdout.strip().split()[-1]

def get_chrome_version_mac() -> Optional[str]:
process = subprocess.Popen(
[
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
"--version",
],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
)
stdout, stderr = process.communicate()
if stderr:
return None
return stdout.strip().split()[-1]

def get_chrome_version_linux() -> Optional[str]:
process = subprocess.Popen(
["google-chrome", "--version"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
)
stdout, stderr = process.communicate()
if stderr:
return None
return stdout.strip().split()[-1]

try:
if sys.platform.startswith("win32"):
return get_chrome_version_windows()
elif sys.platform.startswith("darwin"):
return get_chrome_version_mac()
elif sys.platform.startswith("linux"):
return get_chrome_version_linux()
else:
return None
except FileNotFoundError:
return None
13 changes: 9 additions & 4 deletions tests/_cli/test_envinfo.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
# Copyright 2024 Marimo. All rights reserved.
from marimo._cli.envinfo import (
_get_node_version,
_get_pip_list,
get_system_info,
)


def test_get_node_version() -> None:
node_version = _get_node_version()
system_info = get_system_info()
assert "Binaries" in system_info
assert "Node" in system_info["Binaries"]
node_version = system_info["Binaries"]["Node"]

assert node_version is None or isinstance(node_version, str)


def test_get_pip_list() -> None:
pip_list = _get_pip_list()
system_info = get_system_info()
assert "Requirements" in system_info
pip_list = system_info["Requirements"]

assert isinstance(pip_list, dict)
assert "click" in pip_list
assert "starlette" in pip_list
Expand Down

0 comments on commit ca1a808

Please sign in to comment.