Source code for venv_management.driver

"""The virtualenvwrapper driver interface and factories.
"""

from abc import abstractmethod
from pathlib import Path
from typing import List

from venv_management.environment import preferred_drivers
from venv_management.errors import ImplementationNotFound
from venv_management.extension import Extension, ExtensionError, create_extension, list_extensions

KIND = "driver"

DRIVER_NAMESPACE = f"venv_management.{KIND}"


[docs]class Driver(Extension): """Defines the interface for a virtualenvwrapper-equivalent driver.""" def _kind(self): return KIND def __init__(self, name): """ Args: name: The name of the driver. Raises: ImplementationNotFound: If the the virtualenvwrapper implementation corresponding to the concrete driver type is not available. """ super().__init__(name) self._check_availability() @abstractmethod def _check_availability(self): """Check that the particular virtualenvwrapper implementation required is available. Implementations of this method should either succeed or raise ImplementationNotFound. Raises: ImplementationNotFound: If the implementation is not available. """ raise NotImplementedError
[docs] @abstractmethod def list_virtual_envs(self) -> List[str]: """The virtual environments available to this package. Returns: A list of virtual environment names which can be manipulated by this package. """ raise NotImplementedError
[docs] @abstractmethod def make_virtual_env( self, name, *, python=None, project_path=None, packages=None, requirements_file=None, system_site_packages=False, pip=True, setuptools=True, wheel=True, ): """Make a virtual env. Args: name: The name of the virtual environment. project_path: An optional path to a project which will be associated with the new virtual environment. packages: An optional sequence of package names for packages to be installed. requirements_file: An optional path to a requirements file to be installed. python: The target interpreter for which to create a virtual environment, either the name of the executable, or full path. system_site_packages: If True, give access to the system site packages. pip: If True, or 'latest' the latest pip will be installed. If False, pip will not be installed. If 'bundled', the bundled version will be installed. If a specific version string is given, that version will be installed. setuptools: If True, or 'latest' the latest pip will be installed. If False, pip will not be installed. If 'bundled', the bundled version will be installed. If a specific version string is given, that version will be installed. wheel: If True, or 'latest' the latest pip will be installed. If False, pip will not be installed. If 'bundled', the bundled version will be installed. If a specific version string is given, that version will be installed. Returns: The Path to the root of the virtualenv, or None if the path could not be determined. Raises: PythonNotFound: If the requested Python version could not be found. CommandNotFound: If the required command could not be found. RuntimeError: If the virtualenv could not be created. """ raise NotImplementedError
[docs] @abstractmethod def remove_virtual_env(self, name: str): """Remove a virtual environment. Args: name: The name of the virtual environment to be removed. Raises: ValueError: If the name is empty. """ raise NotImplementedError
[docs] @abstractmethod def resolve_virtual_env(self, name: str) -> Path: """Obtain a path to the virtual environment directory. Args: name: The name of the virtual environment. Returns: The path of the named virtual environment. Raises: ValueError: If there is no virtual environment with the supplied name. """ raise NotImplementedError
[docs]class DriverExtensionError(ExtensionError): """Indicates that an error specific to a driver extension occurred."""
[docs]def create_driver(driver_name) -> Driver: """Create a driver Args: driver_name: The name of the driver to create. Returns: A Driver instance. Raises: ImplementationNotFoundError: If a driver could be created but the driver could not find a working virtualenvwrapper (or equivalent) implementation. """ driver = create_extension( kind=KIND, namespace=DRIVER_NAMESPACE, name=driver_name, exception_type=DriverExtensionError, ) return driver
[docs]def driver_names() -> List[Driver]: """A list of available driver extensions. There is no guarantee that the listed drivers are backed by functioning virtualenvwrapper implementations. """ return list_extensions(DRIVER_NAMESPACE)
_driver = None
[docs]def driver() -> Driver: """Obtain a Driver instance. Returns: A Driver corresponding to an available virtualenvwrapper implementation. Raises: ImplementationNotFound: If no suitable virtualenvwrapper installation was found """ global _driver if _driver is None: reasons = {} for driver_name in preferred_drivers(driver_names()): try: d = create_driver(driver_name) except ImplementationNotFound as e: reasons[driver_name] = str(e) else: _driver = d break else: # no-break raise ImplementationNotFound( "No virtualenv driver backed by a working implementation was found. " "Tried: {tried}.\n" "Reasons:\n" "{reasons}\n" .format( tried=', '.join(map(repr, driver_names())), reasons='\n'.join(' {name}: {reason}'.format( name=name, reason=reason.replace("\n", " ") ) for name, reason in reasons.items()) ) ) return _driver