m2m模型翻译
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

106 lines
3.8 KiB

6 months ago
  1. """HTTP cache implementation.
  2. """
  3. import os
  4. from contextlib import contextmanager
  5. from datetime import datetime
  6. from typing import BinaryIO, Generator, Optional, Union
  7. from pip._vendor.cachecontrol.cache import SeparateBodyBaseCache
  8. from pip._vendor.cachecontrol.caches import SeparateBodyFileCache
  9. from pip._vendor.requests.models import Response
  10. from pip._internal.utils.filesystem import adjacent_tmp_file, replace
  11. from pip._internal.utils.misc import ensure_dir
  12. def is_from_cache(response: Response) -> bool:
  13. return getattr(response, "from_cache", False)
  14. @contextmanager
  15. def suppressed_cache_errors() -> Generator[None, None, None]:
  16. """If we can't access the cache then we can just skip caching and process
  17. requests as if caching wasn't enabled.
  18. """
  19. try:
  20. yield
  21. except OSError:
  22. pass
  23. class SafeFileCache(SeparateBodyBaseCache):
  24. """
  25. A file based cache which is safe to use even when the target directory may
  26. not be accessible or writable.
  27. There is a race condition when two processes try to write and/or read the
  28. same entry at the same time, since each entry consists of two separate
  29. files (https://github.com/psf/cachecontrol/issues/324). We therefore have
  30. additional logic that makes sure that both files to be present before
  31. returning an entry; this fixes the read side of the race condition.
  32. For the write side, we assume that the server will only ever return the
  33. same data for the same URL, which ought to be the case for files pip is
  34. downloading. PyPI does not have a mechanism to swap out a wheel for
  35. another wheel, for example. If this assumption is not true, the
  36. CacheControl issue will need to be fixed.
  37. """
  38. def __init__(self, directory: str) -> None:
  39. assert directory is not None, "Cache directory must not be None."
  40. super().__init__()
  41. self.directory = directory
  42. def _get_cache_path(self, name: str) -> str:
  43. # From cachecontrol.caches.file_cache.FileCache._fn, brought into our
  44. # class for backwards-compatibility and to avoid using a non-public
  45. # method.
  46. hashed = SeparateBodyFileCache.encode(name)
  47. parts = list(hashed[:5]) + [hashed]
  48. return os.path.join(self.directory, *parts)
  49. def get(self, key: str) -> Optional[bytes]:
  50. # The cache entry is only valid if both metadata and body exist.
  51. metadata_path = self._get_cache_path(key)
  52. body_path = metadata_path + ".body"
  53. if not (os.path.exists(metadata_path) and os.path.exists(body_path)):
  54. return None
  55. with suppressed_cache_errors():
  56. with open(metadata_path, "rb") as f:
  57. return f.read()
  58. def _write(self, path: str, data: bytes) -> None:
  59. with suppressed_cache_errors():
  60. ensure_dir(os.path.dirname(path))
  61. with adjacent_tmp_file(path) as f:
  62. f.write(data)
  63. replace(f.name, path)
  64. def set(
  65. self, key: str, value: bytes, expires: Union[int, datetime, None] = None
  66. ) -> None:
  67. path = self._get_cache_path(key)
  68. self._write(path, value)
  69. def delete(self, key: str) -> None:
  70. path = self._get_cache_path(key)
  71. with suppressed_cache_errors():
  72. os.remove(path)
  73. with suppressed_cache_errors():
  74. os.remove(path + ".body")
  75. def get_body(self, key: str) -> Optional[BinaryIO]:
  76. # The cache entry is only valid if both metadata and body exist.
  77. metadata_path = self._get_cache_path(key)
  78. body_path = metadata_path + ".body"
  79. if not (os.path.exists(metadata_path) and os.path.exists(body_path)):
  80. return None
  81. with suppressed_cache_errors():
  82. return open(body_path, "rb")
  83. def set_body(self, key: str, body: bytes) -> None:
  84. path = self._get_cache_path(key) + ".body"
  85. self._write(path, body)