From b93731c1e6ca6dfbb9b98e49594c2b4a8960baba Mon Sep 17 00:00:00 2001 From: AHReccese Date: Thu, 19 Jun 2025 17:07:53 -0400 Subject: [PATCH 01/16] add dedicated Enum for PythonEnvironment (within OS) --- nava/params.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/nava/params.py b/nava/params.py index b161dd7..822a6b0 100644 --- a/nava/params.py +++ b/nava/params.py @@ -24,6 +24,16 @@ class Engine(Enum): AFPLAY = "afplay" +class PythonEnvironment(Enum): + COLAB = "Google Colab" + LOCAL_JUPYTER = "Local Jupyter Notebook or JupyterLab" + VSCODE = "VS Code Notebook" + IPYTHON_TERMINAL = "IPython Terminal" + PLAIN_PYTHON = "Plain Python (.py script)" + UNKNOWN = "Unknown Environment" + + + SOUND_FILE_PLAY_ERROR = "Sound can not play due to some issues." SOUND_FILE_EXIST_ERROR = "Given sound file doesn't exist." SOUND_FILE_PATH_TYPE_ERROR = "Sound file's path should be a string." From cc4588219f2d70c0ba7f627254e49bd0815f5357 Mon Sep 17 00:00:00 2001 From: AHReccese Date: Thu, 19 Jun 2025 17:08:08 -0400 Subject: [PATCH 02/16] env variables params added for vscode notebook --- nava/params.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/nava/params.py b/nava/params.py index 822a6b0..5858c77 100644 --- a/nava/params.py +++ b/nava/params.py @@ -33,6 +33,14 @@ class PythonEnvironment(Enum): UNKNOWN = "Unknown Environment" +# Environment variables typically set by VS Code +VSCODE_ENV_VARS = [ + "VSCODE_PID", # this is often set when running in VS Code + "VSCODE_CWD", # this is often set when running in VS Code + "VSCODE_IPC_HOOK_CLI", + "TERM_PROGRAM", # often set to "vscode" +] + SOUND_FILE_PLAY_ERROR = "Sound can not play due to some issues." SOUND_FILE_EXIST_ERROR = "Given sound file doesn't exist." From 63d616d4b065526a7a978fb1cf2fb3b81201cf79 Mon Sep 17 00:00:00 2001 From: AHReccese Date: Thu, 19 Jun 2025 17:08:31 -0400 Subject: [PATCH 03/16] shell type identifiers for notebooks --- nava/params.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nava/params.py b/nava/params.py index 5858c77..d6a50c1 100644 --- a/nava/params.py +++ b/nava/params.py @@ -41,6 +41,10 @@ class PythonEnvironment(Enum): "TERM_PROGRAM", # often set to "vscode" ] +# Shell type identifiers +SHELL_TYPE_ZMQ = "zmqinteractiveshell" # Jupyter Notebook/Lab +SHELL_TYPE_TERMINAL = "terminalinteractiveshell" # IPython Terminal +SHELL_TYPE_COLAB = "shell" # Fallback seen in Colab SOUND_FILE_PLAY_ERROR = "Sound can not play due to some issues." SOUND_FILE_EXIST_ERROR = "Given sound file doesn't exist." From e7d215635910776133086068014f0dfc2aa94622 Mon Sep 17 00:00:00 2001 From: AHReccese Date: Thu, 19 Jun 2025 17:09:09 -0400 Subject: [PATCH 04/16] play sound in colab using `Audio` module --- nava/functions.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/nava/functions.py b/nava/functions.py index 026350d..70ae2dd 100644 --- a/nava/functions.py +++ b/nava/functions.py @@ -129,6 +129,21 @@ def __play_winsound_flags(sound_path, flags): winsound.PlaySound(sound_path, flags) +def __play_google_colab(sound_path): + """ + Play sound in Google Colab Notebook. + + :param sound_path: sound path + :type sound_path: str + :param loop: sound loop flag + :type loop: bool + :return: None + """ + from IPython.display import Audio, display + audio = Audio(sound_path, autoplay=True) + display(audio) + + @quote def __play_alsa(sound_path, async_mode=False, loop=False): """ From 96c34ca2205268c8bed48e5aec8da70b183ce2f5 Mon Sep 17 00:00:00 2001 From: AHReccese Date: Thu, 19 Jun 2025 17:09:38 -0400 Subject: [PATCH 05/16] detect colab env and use associated dedicated module --- nava/functions.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nava/functions.py b/nava/functions.py index 70ae2dd..79eeb86 100644 --- a/nava/functions.py +++ b/nava/functions.py @@ -280,6 +280,11 @@ def __play_auto(sound_path, async_mode=False, loop=False): :type loop: bool :return: None or sound id """ + env = detect_environment() + if env == PythonEnvironment.COLAB: + return __play_google_colab(sound_path) + # we will add other notebook environment handlers in the future + sys_platform = sys.platform if sys_platform == "win32": return __play_winsound(sound_path, async_mode, loop) From 3f7c534783c001ed1ffed97f965a6b8e15abfd97 Mon Sep 17 00:00:00 2001 From: AHReccese Date: Thu, 19 Jun 2025 17:10:24 -0400 Subject: [PATCH 06/16] implement function to detect python env running the code, either .py or .ipynb in specific notebook environment --- nava/functions.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/nava/functions.py b/nava/functions.py index 79eeb86..d671365 100644 --- a/nava/functions.py +++ b/nava/functions.py @@ -345,3 +345,40 @@ def play_cli(sound_path, loop=False): print("Error: {0}".format(e)) finally: stop_all() + + +def detect_environment(): + """ + Detects the current Python execution environment: + - Google Colab + - Local Jupyter Notebook/Lab + - VS Code Notebook + - IPython Terminal + - Plain Python script + + :return: PythonEnvironment Enum value indicating the environment. + """ + from IPython import get_ipython + ip = get_ipython() + if ip is None: + return PythonEnvironment.PLAIN_PYTHON + + shell_name = ip.__class__.__name__.lower() + # Explicit Google Colab check (most reliable) + try: + import google.colab + return PythonEnvironment.COLAB + except ImportError: + pass + + # VS Code check via known env vars + if any(var in os.environ for var in VSCODE_ENV_VARS): + return PythonEnvironment.VSCODE + + if shell_name == SHELL_TYPE_ZMQ: + return PythonEnvironment.LOCAL_JUPYTER + + if shell_name == SHELL_TYPE_TERMINAL: + return PythonEnvironment.IPYTHON_TERMINAL + + return PythonEnvironment.UNKNOWN From 4f9efe9a800797b87936d8e1f3479b5c49adda6b Mon Sep 17 00:00:00 2001 From: AHReccese Date: Thu, 19 Jun 2025 17:11:23 -0400 Subject: [PATCH 07/16] drop colab hardcode identifier and use import dedicated colab python module instead --- nava/params.py | 1 - 1 file changed, 1 deletion(-) diff --git a/nava/params.py b/nava/params.py index d6a50c1..674b326 100644 --- a/nava/params.py +++ b/nava/params.py @@ -44,7 +44,6 @@ class PythonEnvironment(Enum): # Shell type identifiers SHELL_TYPE_ZMQ = "zmqinteractiveshell" # Jupyter Notebook/Lab SHELL_TYPE_TERMINAL = "terminalinteractiveshell" # IPython Terminal -SHELL_TYPE_COLAB = "shell" # Fallback seen in Colab SOUND_FILE_PLAY_ERROR = "Sound can not play due to some issues." SOUND_FILE_EXIST_ERROR = "Given sound file doesn't exist." From cc15e5f09a9d0c97deae3b44bb26117b3e4e2c91 Mon Sep 17 00:00:00 2001 From: AHReccese Date: Thu, 19 Jun 2025 17:11:37 -0400 Subject: [PATCH 08/16] imports added --- nava/functions.py | 1 + 1 file changed, 1 insertion(+) diff --git a/nava/functions.py b/nava/functions.py index d671365..aa7390a 100644 --- a/nava/functions.py +++ b/nava/functions.py @@ -9,6 +9,7 @@ from .params import OVERVIEW, Engine from .params import SOUND_FILE_PLAY_ERROR, SOUND_FILE_EXIST_ERROR, ENGINE_TYPE_ERROR from .params import SOUND_FILE_PATH_TYPE_ERROR, SOUND_ID_EXIST_ERROR, LOOP_ASYNC_ERROR +from .params import PythonEnvironment, SHELL_TYPE_ZMQ, SHELL_TYPE_TERMINAL, VSCODE_ENV_VARS from .errors import NavaBaseError from . import params From fe3a4b774d7398e108a654fcccad74eaa0884f4c Mon Sep 17 00:00:00 2001 From: AHReccese Date: Thu, 19 Jun 2025 17:33:11 -0400 Subject: [PATCH 09/16] fix the issue with `IPython` import --- nava/functions.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/nava/functions.py b/nava/functions.py index aa7390a..d982f9b 100644 --- a/nava/functions.py +++ b/nava/functions.py @@ -359,8 +359,12 @@ def detect_environment(): :return: PythonEnvironment Enum value indicating the environment. """ - from IPython import get_ipython - ip = get_ipython() + ip = None + try: + from IPython import get_ipython + ip = get_ipython() + except ImportError: + return PythonEnvironment.PLAIN_PYTHON if ip is None: return PythonEnvironment.PLAIN_PYTHON From 16405d41022304568647d43f640a7d43546255dc Mon Sep 17 00:00:00 2001 From: AHReccese Date: Thu, 19 Jun 2025 19:24:23 -0400 Subject: [PATCH 10/16] replace module existence check with `importlib.util` capabilities --- nava/functions.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/nava/functions.py b/nava/functions.py index d982f9b..5261994 100644 --- a/nava/functions.py +++ b/nava/functions.py @@ -5,6 +5,7 @@ import os import shlex from functools import wraps +import importlib.util from .thread import NavaThread from .params import OVERVIEW, Engine from .params import SOUND_FILE_PLAY_ERROR, SOUND_FILE_EXIST_ERROR, ENGINE_TYPE_ERROR @@ -369,12 +370,10 @@ def detect_environment(): return PythonEnvironment.PLAIN_PYTHON shell_name = ip.__class__.__name__.lower() + # Explicit Google Colab check (most reliable) - try: - import google.colab + if importlib.util.find_spec("google.colab") is not None: return PythonEnvironment.COLAB - except ImportError: - pass # VS Code check via known env vars if any(var in os.environ for var in VSCODE_ENV_VARS): From 4d1133faf261fdc401591c49975bc7bab1c963fa Mon Sep 17 00:00:00 2001 From: AHReccese Date: Thu, 19 Jun 2025 19:32:05 -0400 Subject: [PATCH 11/16] add docstring --- nava/params.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nava/params.py b/nava/params.py index 674b326..7b3cbeb 100644 --- a/nava/params.py +++ b/nava/params.py @@ -25,6 +25,8 @@ class Engine(Enum): class PythonEnvironment(Enum): + """Python environment class.""" + COLAB = "Google Colab" LOCAL_JUPYTER = "Local Jupyter Notebook or JupyterLab" VSCODE = "VS Code Notebook" From 0b8a49e6454a78c64eb038e1a5811492cada2eec Mon Sep 17 00:00:00 2001 From: AHReccese Date: Thu, 19 Jun 2025 19:32:23 -0400 Subject: [PATCH 12/16] enhance docstring for `detect_environment` --- nava/functions.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/nava/functions.py b/nava/functions.py index 5261994..5ab2ad0 100644 --- a/nava/functions.py +++ b/nava/functions.py @@ -351,7 +351,9 @@ def play_cli(sound_path, loop=False): def detect_environment(): """ - Detects the current Python execution environment: + Detect the current Python execution environment. + + Supported environments: - Google Colab - Local Jupyter Notebook/Lab - VS Code Notebook From f7e37720b7980dd7aa19036b681ab94b3087b1a1 Mon Sep 17 00:00:00 2001 From: AHReccese Date: Thu, 19 Jun 2025 19:39:55 -0400 Subject: [PATCH 13/16] remove trailing whitespaces --- nava/functions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nava/functions.py b/nava/functions.py index 5ab2ad0..73a7623 100644 --- a/nava/functions.py +++ b/nava/functions.py @@ -362,7 +362,7 @@ def detect_environment(): :return: PythonEnvironment Enum value indicating the environment. """ - ip = None + ip = None try: from IPython import get_ipython ip = get_ipython() From 59ba19712173f2a1db500601d86984eff4503ad8 Mon Sep 17 00:00:00 2001 From: AHReccese Date: Thu, 29 Jan 2026 11:20:48 -0500 Subject: [PATCH 14/16] Refactor __play_google_colab function to include type hints and remove unnecessary parameters in the docstring. --- nava/functions.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/nava/functions.py b/nava/functions.py index 77eb324..05dbb2f 100644 --- a/nava/functions.py +++ b/nava/functions.py @@ -195,15 +195,11 @@ def __play_winsound_flags(sound_path: str, flags: int) -> None: winsound.PlaySound(sound_path, flags) -def __play_google_colab(sound_path): +def __play_google_colab(sound_path: str) -> None: """ Play sound in Google Colab Notebook. :param sound_path: sound path - :type sound_path: str - :param loop: sound loop flag - :type loop: bool - :return: None """ from IPython.display import Audio, display audio = Audio(sound_path, autoplay=True) From 599fd1f1d7155ffbbcb1ad217ad2345c5f0611cb Mon Sep 17 00:00:00 2001 From: AHReccese Date: Sun, 1 Feb 2026 14:10:53 -0500 Subject: [PATCH 15/16] update `return` docstring for `detect_environment` --- nava/functions.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/nava/functions.py b/nava/functions.py index 05dbb2f..4ea47b2 100644 --- a/nava/functions.py +++ b/nava/functions.py @@ -393,8 +393,9 @@ def detect_environment(): - VS Code Notebook - IPython Terminal - Plain Python script - - :return: PythonEnvironment Enum value indicating the environment. + + :return: Enum value indicating the environment. + :rtype: PythonEnvironment """ ip = None try: From 318132856e405e12697f64c339d5447424552d19 Mon Sep 17 00:00:00 2001 From: AHReccese Date: Mon, 2 Feb 2026 12:16:28 -0500 Subject: [PATCH 16/16] Update `detect_environment` function to include return type hint and clean up docstring. --- nava/functions.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/nava/functions.py b/nava/functions.py index 4ea47b2..78319eb 100644 --- a/nava/functions.py +++ b/nava/functions.py @@ -383,7 +383,7 @@ def play_cli(sound_path: str, loop: bool = False) -> None: stop_all() -def detect_environment(): +def detect_environment() -> PythonEnvironment: """ Detect the current Python execution environment. @@ -393,9 +393,6 @@ def detect_environment(): - VS Code Notebook - IPython Terminal - Plain Python script - - :return: Enum value indicating the environment. - :rtype: PythonEnvironment """ ip = None try: