15
15
from itertools import product
16
16
from os .path import splitext
17
17
from pathlib import Path
18
+ from tempfile import TemporaryDirectory
18
19
from types import TracebackType
20
+ from typing import Any , ClassVar
19
21
20
22
from packaging .utils import parse_wheel_filename
21
23
@@ -98,8 +100,13 @@ class InWheel(InTemporaryDirectory):
98
100
On entering, you'll find yourself in the root tree of the wheel. If you've
99
101
asked for an output wheel, then on exit we'll rewrite the wheel record and
100
102
pack stuff up for you.
103
+
104
+ If `out_wheel` is None, we assume the wheel won't be modified and we can
105
+ cache the unpacked wheel for future use.
101
106
"""
102
107
108
+ _whl_cache : ClassVar [dict [Path , TemporaryDirectory [Any ]]] = {}
109
+
103
110
def __init__ (self , in_wheel : Path , out_wheel : Path | None = None ) -> None :
104
111
"""Initialize in-wheel context manager
105
112
@@ -113,9 +120,28 @@ def __init__(self, in_wheel: Path, out_wheel: Path | None = None) -> None:
113
120
"""
114
121
self .in_wheel = in_wheel .absolute ()
115
122
self .out_wheel = None if out_wheel is None else out_wheel .absolute ()
116
- super ().__init__ ()
123
+ self .read_only = out_wheel is None
124
+ self .use_cache = self .in_wheel in self ._whl_cache
125
+
126
+ if self .use_cache :
127
+ logger .debug (
128
+ "Reuse %s for %s" , self ._whl_cache [self .in_wheel ], self .in_wheel
129
+ )
130
+ self ._tmpdir = self ._whl_cache [self .in_wheel ]
131
+ if not self .read_only :
132
+ self ._whl_cache .pop (self .in_wheel )
133
+ else :
134
+ super ().__init__ ()
135
+ if self .read_only :
136
+ self ._whl_cache [self .in_wheel ] = self ._tmpdir
117
137
118
138
def __enter__ (self ) -> Path :
139
+ if self .use_cache or self .read_only :
140
+ if not self .use_cache :
141
+ zip2dir (self .in_wheel , self .name )
142
+ self ._pwd = Path .cwd ()
143
+ os .chdir (self .name )
144
+ return Path (self .name )
119
145
zip2dir (self .in_wheel , self .name )
120
146
return super ().__enter__ ()
121
147
@@ -132,6 +158,16 @@ def __exit__(
132
158
if timestamp :
133
159
date_time = datetime .fromtimestamp (int (timestamp ), tz = timezone .utc )
134
160
dir2zip (self .name , self .out_wheel , date_time )
161
+ if self .use_cache or self .read_only :
162
+ logger .debug (
163
+ "Exiting reused %s for %s" ,
164
+ self ._whl_cache [self .in_wheel ],
165
+ self .in_wheel ,
166
+ )
167
+ os .chdir (self ._pwd )
168
+ if not self .use_cache :
169
+ super ().__exit__ (exc , value , tb )
170
+ return None
135
171
return super ().__exit__ (exc , value , tb )
136
172
137
173
0 commit comments