Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend conda interface: store conda environments in project #1372

Merged
merged 10 commits into from
Mar 28, 2024
43 changes: 37 additions & 6 deletions pyiron_base/project/condaenv.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import os
import subprocess
import warnings

from conda.core.envs_manager import list_all_known_prefixes


class CondaEnvironment:
def __init__(self, env_path):
self._env_path = env_path

def __dir__(self):
return list(self._list_all_known_prefixes_dict().keys()) + ["create"]

Expand All @@ -20,10 +25,36 @@ def __getattr__(self, item):
f"Unknown conda environment {item}. Use one of {self._list_all_known_prefixes_dict()} or create a new one."
)

@staticmethod
def create(env_name, env_file, use_mamba=False):
def create(self, env_name, env_file, use_mamba=False, global_installation=True):
exe = "mamba" if use_mamba else "conda"
subprocess.check_output(
[exe, "env", "create", "-n", env_name, "-f", env_file, "-y"],
universal_newlines=True,
)
env_lst = list_all_known_prefixes()
env_path = os.path.join(os.path.abspath(self._env_path), env_name)
if env_name not in env_lst and env_path not in env_lst:
command_lst = [
exe,
"env",
"create",
]
if not global_installation:
os.makedirs(self._env_path, exist_ok=True)
command_lst += [
"--prefix",
env_path,
]
command_lst += [
"-f",
env_file,
"-y",
]
subprocess.check_output(
command_lst,
universal_newlines=True,
)
else:
warnings.warn(
"The conda environment "
+ env_name
+ " already exists in "
+ str(env_path)
+ "."
)
3 changes: 1 addition & 2 deletions pyiron_base/project/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,7 @@ def conda_environment(self):
raise ImportError(
"You need to have the conda python package installed to access conda environments."
) from None

return CondaEnvironment()
return CondaEnvironment(env_path=os.path.join(self.path, "conda"))

def copy(self):
"""
Expand Down
8 changes: 7 additions & 1 deletion tests/flex/test_executablecontainer_conda.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
import unittest
import warnings
from pyiron_base._tests import TestWithProject


Expand All @@ -25,7 +26,7 @@ def setUpClass(cls):
super().setUpClass()
with open("env.yaml", "w") as f:
f.writelines(conda_env)
cls.project.conda_environment.create(env_name="py312", env_file="env.yaml")
cls.project.conda_environment.create(env_name="py312", env_file="env.yaml", global_installation=False)

@classmethod
def tearDownClass(cls):
Expand All @@ -39,6 +40,11 @@ def test_conda_environment_path(self):
)
job = self.project.create.job.PythonVersionJob(job_name="job_conda_path")
job.server.conda_environment_path = self.project.conda_environment.py312
self.assertTrue(self.project.path in self.project.conda_environment.py312)
self.assertTrue(self.project.conda_environment.py312 in self.project.conda_environment._list_all_known_prefixes_dict().values())
with warnings.catch_warnings(record=True) as w:
self.project.conda_environment.create(env_name="py312", env_file="env.yaml")
self.assertEqual(len(w), 1)
job.run()
self.assertEqual(job.output['stdout'], "Python 3.12.1\n")
self.assertEqual(job["error.out"][0], "Python 3.12.1\n")
Loading