Skip to content
Merged
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
17 changes: 16 additions & 1 deletion conda_self/cli/main_remove.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,25 @@

def configure_parser(parser: argparse.ArgumentParser) -> None:
parser.description = HELP
parser.add_argument("specs", nargs="+", help="Plugins to install")
parser.add_argument("specs", nargs="+", help="Plugins to remove/uninstall")
parser.set_defaults(func=execute)


def execute(args: argparse.Namespace) -> int:
from ..exceptions import SpecsCanNotBeRemoved
from ..query import permanent_dependencies
from ..install import uninstall_specs_in_protected_env

uninstallable_packages = permanent_dependencies()
invalid_specs = []
for spec in args.specs:
if spec in uninstallable_packages:
invalid_specs.append(spec)

if invalid_specs:
raise SpecsCanNotBeRemoved(invalid_specs)

print("Removing plugins:", *args.specs)

uninstall_specs_in_protected_env(args.specs, yes=False)
return 0
2 changes: 1 addition & 1 deletion conda_self/cli/main_update.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def execute(args: argparse.Namespace) -> int:
from conda.reporters import get_spinner

from ..query import check_updates
from ..update import install_package_in_protected_env
from ..install import install_package_in_protected_env
from ..validate import validate_plugin_is_installed

if args.plugin:
Expand Down
5 changes: 5 additions & 0 deletions conda_self/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from typing import Final

PERMANENT_PACKAGES: Final = (
"conda",
)
7 changes: 6 additions & 1 deletion conda_self/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,9 @@

class SpecsAreNotPlugins(CondaError):
def __init__(self, specs: list[str]):
super().__init__(f"The following requested specs are not plugins: {specs}")
super().__init__(f"The following requested specs are not plugins: {specs}")


class SpecsCanNotBeRemoved(CondaError):
def __init__(self, specs: list[str]):
super().__init__(f"Packages '{specs}' can not be removed.")
24 changes: 24 additions & 0 deletions conda_self/update.py → conda_self/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,27 @@ def install_package_in_protected_env(
]
)
return process.returncode


def uninstall_specs_in_protected_env(
specs: list[str],
json: bool = False,
yes: bool = True,
) -> int:
cmd = [
sys.executable,
"-m",
"conda",
"remove",
f"--prefix={sys.prefix}",
*(
("--override-frozen",)
if hasattr(context, "protect_frozen_envs")
else ()
),
*(("--json",) if json else ()),
*(("--yes",) if yes else ()),
*specs
]
process = run(cmd)
return process.returncode
17 changes: 17 additions & 0 deletions conda_self/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from __future__ import annotations

import sys
from functools import cache
from typing import TYPE_CHECKING

from conda.base.context import context
Expand All @@ -13,8 +14,11 @@
PackagesNotFoundError,
)
from conda.models.channel import Channel
from conda.models.prefix_graph import PrefixGraph
from conda.models.version import VersionOrder

from .constants import PERMANENT_PACKAGES

if TYPE_CHECKING:
from collections.abc import Iterable

Expand Down Expand Up @@ -56,3 +60,16 @@ def latest(
if best is None:
raise PackagesNotFoundError(package_name, channels)
return best


@cache
def permanent_dependencies() -> set[str]:
"""Get the full list of dependencies for all the permanent packages."""
installed = PrefixData(sys.prefix)
prefix_graph = PrefixGraph(installed.iter_records())

packages = []
for pkg in PERMANENT_PACKAGES:
node = prefix_graph.get_node_by_name(pkg)
packages.extend([record.name for record in prefix_graph.all_ancestors(node)])
return set(packages)