Source code for scitex_context._detect_environment

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Timestamp: "2025-07-04 11:20:00 (ywatanabe)"
# File: ./src/scitex/gen/_detect_environment.py

"""
Enhanced environment detection for SciTeX.

Provides better discrimination between:
- Python scripts
- IPython console
- Jupyter notebooks
- Interactive Python
"""

import os
import sys
from typing import Literal, Tuple

__all__ = ["detect_environment", "get_output_directory"]

EnvironmentType = Literal["script", "jupyter", "ipython", "interactive", "unknown"]


[docs] def detect_environment() -> EnvironmentType: """ Detect the current execution environment. Returns ------- EnvironmentType One of: 'script', 'jupyter', 'ipython', 'interactive', 'unknown' Examples -------- >>> env = detect_environment() >>> print(f"Running in: {env}") Running in: script """ # Check for Jupyter notebook if "ipykernel" in sys.modules: try: ip = get_ipython() if ip and type(ip).__name__ == "ZMQInteractiveShell": return "jupyter" except NameError: pass # Check for IPython console try: ip = get_ipython() if ip and type(ip).__name__ == "TerminalInteractiveShell": return "ipython" except NameError: pass # Check for regular Python script if sys.argv and sys.argv[0] and sys.argv[0].endswith(".py"): return "script" # Check for interactive Python if hasattr(sys, "ps1"): return "interactive" return "unknown"
[docs] def get_output_directory( specified_path: str, env_type: EnvironmentType = None ) -> Tuple[str, bool]: """ Get the appropriate output directory based on environment. Parameters ---------- specified_path : str The path specified by the user env_type : EnvironmentType, optional Override environment detection Returns ------- tuple[str, bool] (output_directory, should_use_temp) Examples -------- >>> output_dir, use_temp = get_output_directory("data.csv") >>> print(f"Save to: {output_dir}, Temp: {use_temp}") Save to: ./script_out/data.csv, Temp: False """ import inspect if env_type is None: env_type = detect_environment() # For absolute paths, use as-is if specified_path.startswith("/"): return specified_path, False # Get base directory based on environment if env_type == "script": # Use script location try: script_path = inspect.stack()[1].filename if script_path and not script_path.startswith("<"): script_dir = os.path.dirname(os.path.abspath(script_path)) script_name = os.path.splitext(os.path.basename(script_path))[0] base_dir = os.path.join(script_dir, f"{script_name}_out") return os.path.join(base_dir, specified_path), False except: pass elif env_type == "jupyter": # For Jupyter, use current working directory with subdirectory # This keeps outputs near the notebook base_dir = os.path.join(os.getcwd(), "notebook_outputs") return os.path.join(base_dir, specified_path), False elif env_type in ["ipython", "interactive"]: # Use temp directory for console sessions user = os.getenv("USER", "unknown") base_dir = f"/tmp/{user}/{env_type}" return os.path.join(base_dir, specified_path), True # Fallback: use current directory return os.path.join("./output", specified_path), False
[docs] def is_notebook() -> bool: """Check if running in Jupyter notebook.""" return detect_environment() == "jupyter"
[docs] def is_ipython() -> bool: """Check if running in IPython (console or notebook).""" return detect_environment() in ["jupyter", "ipython"]
[docs] def is_script() -> bool: """Check if running as a script.""" return detect_environment() == "script"
# Backward compatibility def is_ipython_legacy() -> bool: """Legacy IPython detection for compatibility.""" try: __IPYTHON__ return True except NameError: return False # EOF