Skip to content

service

dev_tool.services.python.service

log = logging.getLogger(__name__) module-attribute

PythonService

Bases: BaseService

A service class for Python-related operations.

This class provides methods for managing Python virtual environments and dependencies.

The constructor for the PythonService class.

It initializes package managers for dependency management.

Source code in dev_tool/services/python/service.py
def __init__(self) -> None:
    """
    The constructor for the PythonService class.

    It initializes package managers for dependency management.
    """

    super().__init__()

    self.resolver = DependencyResolver()
    self.manager, self.fallback = PackageManagerFactory.create_package_manager()

    if sys.platform == OperatingSystem.WINDOWS:
        EnvironmentVariables.refresh_environment()

resolver = DependencyResolver() instance-attribute

clean_virtual_environment

A method that removes an existing virtual environment.

Source code in dev_tool/services/python/service.py
def clean_virtual_environment(self) -> None:
    """A method that removes an existing virtual environment."""

    message = 'Cleaning virtual environment...'
    self.notification.normal_text(message)

    if VENV.exists():
        self._remove_directory(VENV)

        message = f'Removed virtual environment at {VENV}'
        self.notification.normal_text(message)
    else:
        message = f'No virtual environment found at {VENV}'
        self.notification.warning_banner(message)

        log.debug(message)

create_virtual_environment

A method that creates a Python virtual environment.

Source code in dev_tool/services/python/service.py
def create_virtual_environment(self) -> None:
    """A method that creates a Python virtual environment."""

    message = 'Setting up virtual environment...'
    self.notification.normal_text(message)

    self.install_package_manager()

    if not self.manager.create_virtual_environment():
        message = 'Failed to create virtual environment with preferred manager, falling back...'
        self.notification.warning_text(message)

        log.debug(message)

        if not self.fallback.create_virtual_environment():
            message = 'Failed to create virtual environment with any package manager'
            log.debug(message)

            raise VirtualEnvironmentError(message)

get_available_dependencies

A method that lists all available dependency sources.

This method discovers and returns information about all available dependency sources including requirements files and pyproject.toml extras.

Returns:

  • dict[str, list[str]]

    A dictionary mapping source types to available sources.

Source code in dev_tool/services/python/service.py
def get_available_dependencies(self) -> dict[str, list[str]]:
    """
    A method that lists all available dependency sources.

    This method discovers and returns information about all available
    dependency sources including requirements files and pyproject.toml extras.

    :return: A dictionary mapping source types to available sources.
    """

    return self.resolver.get_available_sources()

install_dependencies

A method that installs Python dependencies.

It requires a virtual environment to be active.

Parameters:

  • requirements_file (Path | None, default: None ) –

    Optional path to a specific requirements file. If provided, installs from this file only.

  • types (list[str] | None, default: None ) –

    Optional list of dependency types to install (e.g., ['development', 'production']). If None, auto-detects.

Source code in dev_tool/services/python/service.py
@is_virtual_environment
def install_dependencies(self, requirements_file: Path | None = None, types: list[str] | None = None) -> None:
    """
    A method that installs Python dependencies.

    It requires a virtual environment to be active.

    :param requirements_file: Optional path to a specific requirements file.
        If provided, installs from this file only.
    :param types: Optional list of dependency types to install
        (e.g., ['development', 'production']). If None, auto-detects.
    """

    self.install_package_manager()

    if requirements_file is not None:
        if not requirements_file.exists():
            message = f'Requirements file not found: {requirements_file}'
            log.debug(message)

            raise DependencyInstallationError(message)

        log.debug(f'Installing from specified requirements file: {requirements_file.name}')
        success = self._install_requirements_file(requirements_file)

        if not success:
            message = f'Failed to install from {requirements_file}'
            log.debug(message)

            raise DependencyInstallationError(message)

        return

    sources = self.resolver.get_strategy(types)

    if not sources:
        message = 'No dependency files found (requirements.txt or pyproject.toml)'
        self.notification.warning_text(message)

        log.debug(message)

        return

    message = f'Found {len(sources)} dependency sources to install'
    self.notification.normal_text(message)

    primary_failed = [
        source.name
        for source in sources
        if not self._install_from_source(source)
    ]

    all_failed = primary_failed.copy()

    if primary_failed and types is None:
        message = 'Primary installation sources failed, trying fallback strategy...'
        self.notification.warning_text(message)

        log.debug(message)

        fallback_sources = self.resolver.get_fallback_strategy(sources)

        if fallback_sources:
            fallback_failed = [
                source.name
                for source in fallback_sources
                if not self._install_from_source(source)
            ]

            all_failed.extend(fallback_failed)

    if all_failed:
        message = f'Failed to install from sources: {", ".join(all_failed)}'
        log.debug(message)

install_dependency

A method that installs a single Python package.

It requires a virtual environment to be active.

Source code in dev_tool/services/python/service.py
@is_virtual_environment
def install_dependency(self) -> None:
    """
    A method that installs a single Python package.

    It requires a virtual environment to be active.
    """

    self.install_package_manager()

    package = get_user_input('Which package do you want to install?')

    if not package:
        message = 'No package specified. Aborting...'
        self.notification.warning_text(message)

        log.debug(message)
        return

    if not self.manager.install_package(package):
        message = 'Failed to install package with preferred manager, falling back...'
        self.notification.warning_text(message)

        log.debug(message)

        if not self.fallback.install_package(package):
            message = f'Failed to install package "{package}" with any package manager'
            log.debug(message)

            raise DependencyInstallationError(message)

    message = f'The {package} package installed successfully.'
    self.notification.normal_text(message)

    log.debug(message)

install_package_manager

A method that installs the preferred package manager.

It falls back to an alternative if the preferred manager cannot be installed.

Source code in dev_tool/services/python/service.py
def install_package_manager(self) -> bool:
    """
    A method that installs the preferred package manager.

    It falls back to an alternative if the preferred manager cannot be installed.
    """

    if self.manager is None or self.fallback is None:
        message = 'Package managers not initialized'
        self.notification.error_banner(message)

        log.debug(message)
        return False

    if self.manager.is_available():
        message = 'uv is already installed.'
        self.notification.normal_text(message)

        log.debug(message)
        return True

    if not self.manager.install_package_manager():
        message = 'Failed to install preferred package manager, falling back...'
        self.notification.warning_text(message)

        log.debug(message)

        if not self.fallback.install_package_manager():
            message = 'Failed to install any package manager'
            log.debug(message)

            raise PackageManagerError(message)

    return False

setup_venv

A method that sets up a complete virtual environment.

Creates a virtual environment if needed, upgrades the package manager, and installs all dependencies.

Parameters:

  • types (list[str] | None, default: None ) –

    Optional list of dependency types to install.

Source code in dev_tool/services/python/service.py
def setup_venv(self, types: list[str] | None = None) -> None:
    """
    A method that sets up a complete virtual environment.

    Creates a virtual environment if needed, upgrades the package manager,
    and installs all dependencies.

    :param types: Optional list of dependency types to install.
    """

    if not VENV.exists():
        self.create_virtual_environment()

    self.upgrade_package_manager()
    self.install_dependencies(types=types)

uninstall_dependencies

A method that uninstalls a Python package.

It requires a virtual environment to be active.

Source code in dev_tool/services/python/service.py
@is_virtual_environment
def uninstall_dependencies(self) -> None:
    """
    A method that uninstalls a Python package.

    It requires a virtual environment to be active.
    """

    self.install_package_manager()

    package = get_user_input('Which package do you want to uninstall?')

    if not package:
        message = 'No package specified. Aborting...'
        self.notification.warning_text(message)

        log.debug(message)
        return

    installed = self.manager.list_installed_packages()

    if not installed:
        installed = self.fallback.list_installed_packages()

    if package not in installed:
        message = f'The "{package}" package is not installed.'
        self.notification.warning_text(message)

        log.debug(message)
        return

    if not self.manager.uninstall_package(package):
        message = 'Failed to uninstall package with preferred manager, falling back...'
        self.notification.warning_text(message)

        log.debug(message)

        if not self.fallback.uninstall_package(package):
            message = f'Failed to uninstall package "{package}" with any package manager'
            log.debug(message)

            raise PackageUninstallationError(message)

    message = f'The {package} package uninstalled successfully.'
    self.notification.normal_text(message)

    log.debug(message)

upgrade_package_manager

A method that upgrades the package manager to the latest version.

It requires a virtual environment to be active.

Source code in dev_tool/services/python/service.py
@is_virtual_environment
def upgrade_package_manager(self) -> None:
    """
    A method that upgrades the package manager to the latest version.

    It requires a virtual environment to be active.
    """

    if not self.manager.upgrade_package_manager():
        message = 'Failed to upgrade preferred package manager, falling back...'
        self.notification.warning_text(message)

        log.debug(message)

        if not self.fallback.upgrade_package_manager():
            message = 'Failed to upgrade any package manager'
            log.debug(message)

            raise PackageManagerError(message)