__init__.py 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. """Application data stored by virtualenv."""
  2. from __future__ import annotations
  3. import logging
  4. import os
  5. import shutil
  6. from typing import TYPE_CHECKING, Any
  7. from platformdirs import user_cache_dir, user_data_dir
  8. from .na import AppDataDisabled
  9. from .read_only import ReadOnlyAppData
  10. from .via_disk_folder import AppDataDiskFolder
  11. from .via_tempdir import TempAppData
  12. if TYPE_CHECKING:
  13. from collections.abc import Mapping
  14. from .base import AppData
  15. LOGGER = logging.getLogger(__name__)
  16. def _default_app_data_dir(env: Mapping[str, str]) -> str:
  17. key = "VIRTUALENV_OVERRIDE_APP_DATA"
  18. if key in env:
  19. return env[key]
  20. return _cache_dir_with_migration()
  21. def _cache_dir_with_migration() -> str:
  22. new_dir = user_cache_dir(appname="virtualenv", appauthor="pypa")
  23. old_dir = user_data_dir(appname="virtualenv", appauthor="pypa")
  24. if new_dir == old_dir:
  25. return new_dir
  26. if os.path.isdir(old_dir) and not os.path.isdir(new_dir):
  27. LOGGER.info("migrating app data from %s to %s", old_dir, new_dir)
  28. try:
  29. shutil.move(old_dir, new_dir)
  30. except OSError as exception:
  31. LOGGER.warning(
  32. "could not migrate app data from %s to %s: %r, using old location", old_dir, new_dir, exception
  33. )
  34. return old_dir
  35. return new_dir
  36. def make_app_data(folder: str | None, **kwargs: Any) -> AppData: # noqa: ANN401
  37. is_read_only = kwargs.pop("read_only")
  38. env = kwargs.pop("env")
  39. if kwargs: # py3+ kwonly
  40. msg = "unexpected keywords: {}"
  41. raise TypeError(msg)
  42. if folder is None:
  43. folder = _default_app_data_dir(env)
  44. folder = os.path.abspath(folder)
  45. if is_read_only:
  46. return ReadOnlyAppData(folder)
  47. try:
  48. os.makedirs(folder, exist_ok=True)
  49. LOGGER.debug("created app data folder %s", folder)
  50. except OSError as exception:
  51. LOGGER.info("could not create app data folder %s due to %r", folder, exception)
  52. if os.access(folder, os.W_OK):
  53. return AppDataDiskFolder(folder)
  54. LOGGER.debug("app data folder %s has no write access", folder)
  55. return TempAppData()
  56. __all__ = (
  57. "AppDataDisabled",
  58. "AppDataDiskFolder",
  59. "ReadOnlyAppData",
  60. "TempAppData",
  61. "make_app_data",
  62. )