1616logger = logging .getLogger (__name__ )
1717
1818
19- class WheelCache (object ):
20- """A cache of wheels for future installs."""
19+ class Cache (object ):
20+ """An abstract class - provides cache directories for data from links
2121
22- def __init__ (self , cache_dir , format_control ):
23- """Create a wheel cache.
2422
2523 :param cache_dir: The root of the cache.
2624 :param format_control: A pip.index.FormatControl object to limit
2725 binaries being read from the cache.
28- """
29- self ._cache_dir = expanduser (cache_dir ) if cache_dir else None
30- self ._format_control = format_control
31-
32- def get_cache_path_for_link (self , link ):
33- """
34- Return a directory to store cached wheels in for link.
26+ :param allowed_formats: which formats of files the cache should store.
27+ ('binary' and 'source' are the only allowed values)
28+ """
3529
36- Because there are M wheels for any one sdist, we provide a directory
37- to cache them in, and then consult that directory when looking up
38- cache hits.
30+ def __init__ (self , cache_dir , format_control , allowed_formats ):
31+ super (Cache , self ).__init__ ()
32+ self .cache_dir = expanduser (cache_dir ) if cache_dir else None
33+ self .format_control = format_control
34+ self .allowed_formats = allowed_formats
3935
40- We only insert things into the cache if they have plausible version
41- numbers, so that we don't contaminate the cache with things that were
42- not unique. E.g. ./package might have dozens of installs done for it
43- and build a version of 0.0...and if we built and cached a wheel, we'd
44- end up using the same wheel even if the source has been edited.
36+ _valid_formats = {"source" , "binary" }
37+ assert self .allowed_formats .union (_valid_formats ) == _valid_formats
4538
46- :param link: The link of the sdist for which this will cache wheels.
39+ def _get_cache_path_parts (self , link ):
40+ """Get parts of part that must be os.path.joined with cache_dir
4741 """
4842
4943 # We want to generate an url to use as our cache key, we don't want to
@@ -65,37 +59,82 @@ def get_cache_path_for_link(self, link):
6559 # FS.
6660 parts = [hashed [:2 ], hashed [2 :4 ], hashed [4 :6 ], hashed [6 :]]
6761
68- # Inside of the base location for cached wheels, expand our parts and
69- # join them all together.
70- return os .path .join (self ._cache_dir , "wheels" , * parts )
71-
72- def cached_wheel (self , link , package_name ):
73- not_cached = (
74- not self ._cache_dir or
75- not link or
76- link .is_wheel or
77- not link .is_artifact or
78- not package_name
79- )
62+ return parts
8063
81- if not_cached :
82- return link
64+ def _get_candidates (self , link , package_name ):
65+ can_not_cache = (
66+ not self .cache_dir or
67+ not package_name or
68+ not link
69+ )
70+ if can_not_cache :
71+ return []
8372
8473 canonical_name = canonicalize_name (package_name )
8574 formats = pip .index .fmt_ctl_formats (
86- self ._format_control , canonical_name
75+ self .format_control , canonical_name
8776 )
88- if "binary" not in formats :
89- return link
90- root = self .get_cache_path_for_link (link )
77+ if not self .allowed_formats .intersection (formats ):
78+ return []
79+
80+ root = self .get_path_for_link (link )
9181 try :
92- wheel_names = os .listdir (root )
82+ return os .listdir (root )
9383 except OSError as err :
9484 if err .errno in {errno .ENOENT , errno .ENOTDIR }:
95- return link
85+ return []
9686 raise
87+
88+ def get_path_for_link (self , link ):
89+ """Return a directory to store cached items in for link.
90+ """
91+ raise NotImplementedError ()
92+
93+ def get (self , link , package_name ):
94+ """Returns a link to a cached item if it exists, otherwise returns the
95+ passed link.
96+ """
97+ raise NotImplementedError ()
98+
99+ def _link_for_candidate (self , link , candidate ):
100+ root = self .get_path_for_link (link )
101+ path = os .path .join (root , candidate )
102+
103+ return pip .index .Link (path_to_url (path ))
104+
105+
106+ class WheelCache (Cache ):
107+ """A cache of wheels for future installs.
108+ """
109+
110+ def __init__ (self , cache_dir , format_control ):
111+ super (WheelCache , self ).__init__ (cache_dir , format_control , {"binary" })
112+
113+ def get_path_for_link (self , link ):
114+ """Return a directory to store cached wheels for link
115+
116+ Because there are M wheels for any one sdist, we provide a directory
117+ to cache them in, and then consult that directory when looking up
118+ cache hits.
119+
120+ We only insert things into the cache if they have plausible version
121+ numbers, so that we don't contaminate the cache with things that were
122+ not unique. E.g. ./package might have dozens of installs done for it
123+ and build a version of 0.0...and if we built and cached a wheel, we'd
124+ end up using the same wheel even if the source has been edited.
125+
126+ :param link: The link of the sdist for which this will cache wheels.
127+ """
128+ parts = self ._get_cache_path_parts (link )
129+
130+ # Inside of the base location for cached wheels, expand our parts and
131+ # join them all together.
132+ return os .path .join (self .cache_dir , "wheels" , * parts )
133+
134+ def get (self , link , package_name ):
97135 candidates = []
98- for wheel_name in wheel_names :
136+
137+ for wheel_name in self ._get_candidates (link , package_name ):
99138 try :
100139 wheel = Wheel (wheel_name )
101140 except InvalidWheelFilename :
@@ -104,8 +143,8 @@ def cached_wheel(self, link, package_name):
104143 # Built for a different python/arch/etc
105144 continue
106145 candidates .append ((wheel .support_index_min (), wheel_name ))
146+
107147 if not candidates :
108148 return link
109- candidates .sort ()
110- path = os .path .join (root , candidates [0 ][1 ])
111- return pip .index .Link (path_to_url (path ))
149+
150+ return self ._link_for_candidate (link , min (candidates )[1 ])
0 commit comments