Skip to content
This repository was archived by the owner on Nov 6, 2025. It is now read-only.
Open
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
10 changes: 7 additions & 3 deletions src/pymodaq_utils/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
if TYPE_CHECKING:
from pyqtgraph import Parameter

from pymodaq_utils.env_utils import guess_virtual_environment, hash_pymodaq_packages_version

try:
USER = environ['USERNAME'] if sys.platform == 'win32' else environ['USER']
Expand All @@ -26,6 +27,8 @@
KeyType = TypeVar('KeyType')


PYMODAQ_USER_FOLDER_NAME = f'.pymodaq_{ guess_virtual_environment() }_{ hash_pymodaq_packages_version() }'

def deep_update(mapping: Dict[KeyType, Any], *updating_mappings: Dict[KeyType, Any]) -> Dict[KeyType, Any]:
""" Make sure a dictionary is updated using another dict in any nested level
Taken from Pydantic v1
Expand Down Expand Up @@ -126,11 +129,12 @@ def get_set_local_dir(user=False) -> Path:
-------
Path: the local path
"""

if user:
local_path = get_set_path(Path.home(), '.pymodaq')
local_dir = get_set_path(Path.home(), PYMODAQ_USER_FOLDER_NAME)
else:
local_path = get_set_path(CONFIG_BASE_PATH, '.pymodaq')
return local_path
local_dir = get_set_path(CONFIG_BASE_PATH, '.pymodaq')
return local_dir


def get_config_file(config_file_name: str, user=False):
Expand Down
39 changes: 39 additions & 0 deletions src/pymodaq_utils/env_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import os
import sys

from importlib import metadata
from importlib.metadata import PackageNotFoundError
from pathlib import Path

def guess_virtual_environment() -> str:
'''
Try to guess the current python environment used.

Returns
-------
str: the guessed environment name or the string "unknown"
'''
def _venv_name_or_path():
#Try to guess from system environment
for var in ['VIRTUAL_ENV', 'CONDA_DEFAULT_ENV', 'PYENV_VERSION', 'TOX_ENV_NAME']:
value = os.environ.get(var)
if value:
return value
#if true, probably running in a venv
if sys.prefix != sys.base_prefix:
return sys.prefix
return 'unknown'
return Path(_venv_name_or_path()).name


def hash_pymodaq_packages_version() -> str:
import hashlib
versions = []
for package in ['pymodaq_utils', 'pymodaq_data', 'pymodaq_gui', 'PyMoDAQ']:
try:
versions.append(metadata.version(package))
except PackageNotFoundError:
#package not found, it can be skipped
pass
hashed = hashlib.sha256(''.join(versions).encode())
return hashed.digest()[:8].hex()
20 changes: 1 addition & 19 deletions src/pymodaq_utils/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,32 +10,14 @@
from pymodaq_utils import config as configmod
from pymodaq_utils.config import get_set_local_dir
from pymodaq_utils.logger import set_logger, get_module_name

from pymodaq_utils.env_utils import guess_virtual_environment

logger = set_logger(get_module_name(__file__))

config = configmod.Config()


def guess_virtual_environment() -> str:
'''
Try to guess the current python environment used.

Returns
-------
str: the guessed environment name or the string "unknown"
'''
def _venv_name_or_path():
#Try to guess from system environment
for var in ['VIRTUAL_ENV', 'CONDA_DEFAULT_ENV', 'PYENV_VERSION', 'TOX_ENV_NAME']:
value = os.environ.get(var)
if value:
return value
#if true, probably running in a venv
if sys.prefix != sys.base_prefix:
return sys.prefix
return 'unknown'
return Path(_venv_name_or_path()).name


class EnvironmentBackupManager:
Expand Down
40 changes: 31 additions & 9 deletions tests/environment_test.py
Original file line number Diff line number Diff line change
@@ -1,40 +1,41 @@
import os, sys
import importlib
import pytest


from pymodaq_utils.environment import guess_virtual_environment, PythonEnvironment
from pymodaq_utils.env_utils import guess_virtual_environment, hash_pymodaq_packages_version
from pymodaq_utils.environment import PythonEnvironment


POSSIBLE_VENV_VARIABLES = ['VIRTUAL_ENV', 'CONDA_DEFAULT_ENV', 'PYENV_VERSION', 'TOX_ENV_NAME']
class TestGuessVirtualEnvironment:

@pytest.mark.parametrize("var", POSSIBLE_VENV_VARIABLES)
@pytest.mark.parametrize('var', POSSIBLE_VENV_VARIABLES)
def test_from_environment_var(self, monkeypatch, var):
venv_name = "if_your_environment_is_called_like_that_you_should_probably_change_it"
venv_name = 'if_your_environment_is_called_like_that_you_should_probably_change_it'

# set one of the possible environment variable to the var name value
# and remove the others
monkeypatch.setenv(var, os.path.join("/home/./folder/", venv_name))
monkeypatch.setenv(var, os.path.join('/home/./folder/', venv_name))
for other in [o for o in POSSIBLE_VENV_VARIABLES if o != var]:
monkeypatch.delenv(other, raising=False)

assert guess_virtual_environment() == venv_name


def test_from_prefix(self, monkeypatch):
venv_name = "if_your_environment_is_called_like_that_you_should_probably_change_it"
venv_name = 'if_your_environment_is_called_like_that_you_should_probably_change_it'
for var in POSSIBLE_VENV_VARIABLES:
monkeypatch.delenv(var, raising=False)

monkeypatch.setattr(sys, "prefix", os.path.join("/home/./folder/", venv_name))
monkeypatch.setattr(sys, 'prefix', os.path.join('/home/./folder/', venv_name))
assert guess_virtual_environment() == venv_name


def test_unknown(self, monkeypatch):
for var in POSSIBLE_VENV_VARIABLES:
monkeypatch.delenv(var, raising=False)

monkeypatch.setattr(sys, "prefix", sys.base_prefix)
monkeypatch.setattr(sys, 'prefix', sys.base_prefix)
assert guess_virtual_environment() == 'unknown'

class TestPythonEnvironment:
Expand Down Expand Up @@ -71,4 +72,25 @@ def test_freeze(self):
e1 = PythonEnvironment.from_freeze()
e2 = PythonEnvironment.from_freeze()

assert e1 == e2, "Two pip freeze in a row don't return the same environment. Ensure no pip install are running."
assert e1 == e2, 'Two pip freeze in a row don\'t return the same environment. Ensure no pip install are running.'

class TestHashPymodaqPackageVersion:
@pytest.mark.parametrize(
'versions, hashed', [
({'pymodaq_utils': '1.0.0', 'pymodaq_data': '2.0.0', 'pymodaq_gui': '3.0.0', 'PyMoDAQ': '4.0.0'}, '94722337cbb21550'),
({'pymodaq_utils': '9.9.9', 'pymodaq_data': '8.8.8', 'pymodaq_gui': '7.7.7', 'PyMoDAQ': '6.6.6'}, 'eb57be0fff8e14f5')
]
)
def test_hash_pymodaq_package_version(self, monkeypatch, versions, hashed):
def mock_version(package):
return versions[package]

monkeypatch.setattr(importlib.metadata, 'version', mock_version)

assert hash_pymodaq_packages_version() == hashed

def test_hash_similar(self):
h1 = hash_pymodaq_packages_version()
h2 = hash_pymodaq_packages_version()

assert h1 == h2, 'Two hashes of PyMoDAQ package version numbers in a row return different values. Ensure no pip install are'
Loading