Skip to content

Commit

Permalink
Improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
oliverweissl committed Nov 29, 2024
1 parent 06caa87 commit 6f12858
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 32 deletions.
16 changes: 10 additions & 6 deletions conda_dependency_cleaner/_clean_environment_from_file.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
from conda.exports import linked, linked_data
from conda.env.env import Environment, from_file
from conda.exports import linked
from conda.models.dist import Dist

from .utility import get_dependency_graph, to_yaml_patch, Dependency

from .utility import Dependency, get_dependency_graph, to_yaml_patch


def clean_environment_from_file(
Expand All @@ -27,22 +26,27 @@ def clean_environment_from_file(
# Extract all packages that are roots (i.e have no packages depend on them).
roots = [k for k, v in graph.in_degree if v < 1]
# Get filtered dependencies for conda and pip
conda_dependencies = _get_filtered_dependencies(env.dependencies.get("conda"), roots, exclude_version, exclude_build)
conda_dependencies = _get_filtered_dependencies(
env.dependencies.get("conda"), roots, exclude_version, exclude_build
)

# For now we can only filter conda packages
# TODO: maybe incorporate filtering for pip
pip_deps: list[str] | None = env.dependencies.get("pip")
new_dependencies = conda_dependencies + ([{"pip": pip_deps}] if pip_deps else [])


env_dict = env.to_dict()
env_dict["dependencies"] = new_dependencies

path = new_file_name or env.filename
print(path)
with open(path, "wb") as stream:
to_yaml_patch(stream=stream, obj=env_dict)

def _get_filtered_dependencies(dependencies: list[str] | None, roots: list[str], ev: bool, eb: bool) -> list[str]:

def _get_filtered_dependencies(
dependencies: list[str] | None, roots: list[str], ev: bool, eb: bool
) -> list[str]:
"""
Get a list of filtered dependencies.
Expand Down
6 changes: 2 additions & 4 deletions conda_dependency_cleaner/clean.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,10 @@ def main() -> None:
parser.add_argument(
"--exclude-version",
help="Allows to exclude version of the dependency.",
action='store_true'
action="store_true",
)
parser.add_argument(
"--exclude-build",
help="Allows to exclude build of the dependency.",
action='store_true'
"--exclude-build", help="Allows to exclude build of the dependency.", action="store_true"
)
parser.add_argument(
"-h",
Expand Down
6 changes: 3 additions & 3 deletions conda_dependency_cleaner/utility/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""A collection of implemented utility functions and Classes."""

from ._to_yaml_patch import to_yaml_patch
from ._get_dependeny_graph import get_dependency_graph
from ._dependency import Dependency
from ._get_dependeny_graph import get_dependency_graph
from ._to_yaml_patch import to_yaml_patch

__all__ = ["to_yaml_patch", "get_dependency_graph", "Dependency"]
__all__ = ["to_yaml_patch", "get_dependency_graph", "Dependency"]
4 changes: 3 additions & 1 deletion conda_dependency_cleaner/utility/_dependency.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from dataclasses import dataclass, field


@dataclass
class Dependency:
"""A class representing a dependency of the conda environment."""

full_name: str
exclude_version: bool
exclude_build: bool
Expand All @@ -25,4 +27,4 @@ def __repr__(self) -> str:
"""
v = "" if self.exclude_version else f"=={self.version}"
b = "" if (self.exclude_build or self.exclude_version) else f"={self.build}"
return f"{self.name}{v}{b}"
return f"{self.name}{v}{b}"
1 change: 0 additions & 1 deletion conda_dependency_cleaner/utility/_to_yaml_patch.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,4 @@ def to_yaml_patch(stream: BinaryIO, obj: dict[str, Any]) -> None:
parser.indent(mapping=2, offset=2, sequence=4)
parser.default_flow_style = False
parser.sort_base_mapping_type_on_output = False

parser.dump(obj, stream)
51 changes: 34 additions & 17 deletions tests/test_clean.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,44 @@ def test_clean(mocker: Mock) -> None:
:param mocker: The mock object.
"""
with tempfile.TemporaryDirectory() as temp_dir:
test_env_file = f"{os.path.dirname(os.path.realpath(__file__))}/test_env.yml"
env: Environment = from_file(test_env_file)
# Create the test environment
subprocess.run(["conda", "env", "create", "-f", test_env_file])
initial_env_file = f"{os.path.dirname(os.path.realpath(__file__))}/test_env.yml"
clean_env_file = f"{os.path.dirname(os.path.realpath(__file__))}/clean_test_env.yml"
clean_env: Environment = from_file(clean_env_file)

# Create the test environment
base_env_file = f"{temp_dir}/test.yml"
subprocess.run(["conda", "env", "export", "-n", env.name ,"-f", base_env_file])
base_env: Environment = from_file(base_env_file)
subprocess.run(["conda", "env", "remove", "-p", base_env.prefix, "-y"])

base_env = _conda_operations(initial_env_file, base_env_file)

# Clean the environment
clean_env_file = f"{temp_dir}/test_clean.yml"
subprocess.run(["clean-yaml", base_env_file, "-nf", clean_env_file])
cleaned_env: Environment = from_file(clean_env_file)
cleaned_env.name += "Clean" # Change name
cleaned_env_file = f"{temp_dir}/test_clean.yml"
subprocess.run(["clean-yaml", base_env_file, "-nf", cleaned_env_file])
_remove_conda_env(base_env)

cleaned_env = _conda_operations(cleaned_env_file, cleaned_env_file)
_remove_conda_env(cleaned_env)

with open(clean_env_file, "wb") as stream:
to_yaml_patch(stream, cleaned_env.to_dict())
assert cleaned_env.dependencies == clean_env.dependencies, "Error: Dependencies are different."


def _conda_operations(initial_env: str, new_env: str) -> Environment:
"""
Create a conda environment based on a environment file, then export it to a new file.
# Create and remove cleaned environment
subprocess.run(["conda", "env", "create", "-f", clean_env_file])
subprocess.run(["conda", "env", "remove", "-p", cleaned_env.prefix, "-y"])
:param initial_env: The environment file.
:param new_env: The new environment file.
:return: The environment loaded as a python object.
"""
env = from_file(initial_env)
subprocess.run(["conda", "env", "create", "-f", initial_env])
subprocess.run(["conda", "env", "export", "-n", env.name, "-f", new_env])
return env


def _remove_conda_env(env: Environment) -> None:
"""
Remove a conda environment from the system.
:param env: The environment to remove.
"""
subprocess.run(["conda", "env", "remove", "-n", env.name, "-y"])

0 comments on commit 6f12858

Please sign in to comment.