Skip to content

Commit

Permalink
Kernel: Add comm handler to get Python env info
Browse files Browse the repository at this point in the history
- This will be used from Spyder for a new status bar widget which will
display this info.
- Also add a test for it.
  • Loading branch information
ccordoba12 committed Aug 13, 2024
1 parent 0eee303 commit 795256e
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 2 deletions.
33 changes: 33 additions & 0 deletions spyder_kernels/console/kernel.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@
from spyder_kernels.comms.frontendcomm import FrontendComm
from spyder_kernels.comms.decorators import (
register_comm_handlers, comm_handler)
from spyder_kernels.utils.pythonenv import (
get_env_dir,
is_conda_env,
is_pyenv_env,
PythonEnvInfo,
PythonEnvType,
)
from spyder_kernels.utils.iofuncs import iofunctions
from spyder_kernels.utils.mpl import automatic_backend, MPL_BACKENDS_TO_SPYDER
from spyder_kernels.utils.nsview import (
Expand Down Expand Up @@ -81,6 +88,9 @@ def __init__(self, *args, **kwargs):
# To track the interactive backend
self.interactive_backend = None

# To save the python env info
self.pythonenv_info: PythonEnvInfo = {}

@property
def kernel_info(self):
# Used for checking correct version by spyder
Expand Down Expand Up @@ -756,6 +766,29 @@ def update_syspath(self, path_dict, new_path_dict):
else:
os.environ.pop('PYTHONPATH', None)

@comm_handler
def get_pythonenv_info(self):
"""Get the Python env info in which this kernel is installed."""
# We only need to compute this once
if not self.pythonenv_info:
path = sys.executable.replace("pythonw.exe", "python.exe")

if is_conda_env(pyexec=path):
env_type = PythonEnvType.Conda
elif is_pyenv_env(path):
env_type = PythonEnvType.PyEnv
else:
env_type = PythonEnvType.Custom

self.pythonenv_info = PythonEnvInfo(
path=path,
env_type=env_type,
name=get_env_dir(path, only_dir=True),
py_version='.'.join([str(n) for n in sys.version_info[:3]]),
)

return self.pythonenv_info

# -- Private API ---------------------------------------------------
# --- For the Variable Explorer
def _get_len(self, var):
Expand Down
26 changes: 24 additions & 2 deletions spyder_kernels/console/tests/test_console_kernel.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@
import numpy as np

# Local imports
from spyder_kernels.comms.commbase import CommBase
from spyder_kernels.customize.spyderpdb import SpyderPdb
from spyder_kernels.utils.iofuncs import iofunctions
from spyder_kernels.utils.pythonenv import PythonEnvType
from spyder_kernels.utils.test_utils import get_kernel, get_log_text
from spyder_kernels.customize.spyderpdb import SpyderPdb
from spyder_kernels.comms.commbase import CommBase

# =============================================================================
# Constants and utility functions
Expand Down Expand Up @@ -1410,5 +1411,26 @@ def test_hard_link_pdb(tmpdir):
assert pdb_obj.canonic(str(d)) == pdb_obj.canonic(str(hard_link))


@pytest.mark.skipif(not os.environ.get('CI'), reason="Only works on CIs")
def test_get_pythonenv_info(kernel):
"""Test the output we get from this method."""
output = kernel.get_pythonenv_info()
assert output["path"] == sys.executable

if os.environ.get('USE_CONDA'):
assert output["name"] == "test"
assert output["type"] == PythonEnvType.Conda
else:
assert output["type"] in [
# This Custom here accounts for Linux packagers that run our tests
# in their CIs
PythonEnvType.Custom,
PythonEnvType.Conda,
]

# Check this key is present. Otherwise we'll break Spyder.
assert output["py_version"]


if __name__ == "__main__":
pytest.main()
19 changes: 19 additions & 0 deletions spyder_kernels/utils/pythonenv.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,27 @@
"""Utilities to get information about Python environments."""

# Standard library imports
from __future__ import annotations
import os
from pathlib import Path
from typing import TypedDict


class PythonEnvType:
"""Enum with the different types of Python environments we can detect."""

Conda = "conda"
PyEnv = "pyenv"
Custom = "custom" # Nor Conda or Pyenv


class PythonEnvInfo(TypedDict):
"""Schema for Python environment information."""

path: str
env_type: PythonEnvType
name: str
py_version: str


def add_quotes(path):
Expand Down

0 comments on commit 795256e

Please sign in to comment.