session.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. from __future__ import annotations
  2. import json
  3. import logging
  4. import sys
  5. from typing import TYPE_CHECKING
  6. if TYPE_CHECKING:
  7. from types import TracebackType
  8. from python_discovery import PythonInfo
  9. from virtualenv.activation.activator import Activator
  10. from virtualenv.app_data.base import AppData
  11. from virtualenv.create.creator import Creator
  12. from virtualenv.seed.seeder import Seeder
  13. if sys.version_info >= (3, 11):
  14. from typing import Self
  15. else:
  16. from typing_extensions import Self
  17. LOGGER = logging.getLogger(__name__)
  18. class Session:
  19. """Represents a virtual environment creation session."""
  20. def __init__( # noqa: PLR0913
  21. self,
  22. verbosity: int,
  23. app_data: AppData,
  24. interpreter: PythonInfo,
  25. creator: Creator,
  26. seeder: Seeder,
  27. activators: list[Activator],
  28. ) -> None:
  29. self._verbosity = verbosity
  30. self._app_data = app_data
  31. self._interpreter = interpreter
  32. self._creator = creator
  33. self._seeder = seeder
  34. self._activators = activators
  35. @property
  36. def verbosity(self) -> int:
  37. """The verbosity of the run."""
  38. return self._verbosity
  39. @property
  40. def interpreter(self) -> PythonInfo:
  41. """Create a virtual environment based on this reference interpreter."""
  42. return self._interpreter
  43. @property
  44. def creator(self) -> Creator:
  45. """The creator used to build the virtual environment (must be compatible with the interpreter)."""
  46. return self._creator
  47. @property
  48. def seeder(self) -> Seeder:
  49. """The mechanism used to provide the seed packages (pip, setuptools, wheel)."""
  50. return self._seeder
  51. @property
  52. def activators(self) -> list[Activator]:
  53. """Activators used to generate activations scripts."""
  54. return self._activators
  55. def run(self) -> None:
  56. self._create()
  57. self._seed()
  58. self._activate()
  59. self.creator.pyenv_cfg.write()
  60. def _create(self) -> None:
  61. LOGGER.info("create virtual environment via %s", self.creator)
  62. self.creator.run()
  63. LOGGER.debug(_DEBUG_MARKER)
  64. LOGGER.debug("%s", _Debug(self.creator))
  65. def _seed(self) -> None:
  66. if self.seeder is not None and self.seeder.enabled:
  67. LOGGER.info("add seed packages via %s", self.seeder)
  68. self.seeder.run(self.creator)
  69. def _activate(self) -> None:
  70. if self.activators:
  71. active = ", ".join(type(i).__name__.replace("Activator", "") for i in self.activators)
  72. LOGGER.info("add activators for %s", active)
  73. for activator in self.activators:
  74. activator.generate(self.creator)
  75. def __enter__(self) -> Self:
  76. return self
  77. def __exit__(
  78. self,
  79. exc_type: type[BaseException] | None,
  80. exc_val: BaseException | None,
  81. exc_tb: TracebackType | None,
  82. ) -> None:
  83. self._app_data.close()
  84. _DEBUG_MARKER = "=" * 30 + " target debug " + "=" * 30
  85. class _Debug:
  86. """lazily populate debug."""
  87. def __init__(self, creator: Creator) -> None:
  88. self.creator = creator
  89. def __repr__(self) -> str:
  90. return json.dumps(self.creator.debug, indent=2)
  91. __all__ = [
  92. "Session",
  93. ]