10
10
from ._log import log
11
11
from .errors import DistutilsFileError , DistutilsInternalError
12
12
13
- # cache for by mkpath() -- in addition to cheapening redundant calls,
14
- # eliminates redundant "creating /foo/bar/baz" messages in dry-run mode
15
- _path_created = set ()
13
+
14
+ class SkipRepeatAbsolutePaths (set ):
15
+ """
16
+ Cache for mkpath.
17
+
18
+ In addition to cheapening redundant calls, eliminates redundant
19
+ "creating /foo/bar/baz" messages in dry-run mode.
20
+ """
21
+
22
+ def __init__ (self ):
23
+ SkipRepeatAbsolutePaths .instance = self
24
+
25
+ @classmethod
26
+ def clear (cls ):
27
+ super (cls , cls .instance ).clear ()
28
+
29
+ def wrap (self , func ):
30
+ @functools .wraps (func )
31
+ def wrapper (path , * args , ** kwargs ):
32
+ if path .absolute () in self :
33
+ return
34
+ self .add (path .absolute ())
35
+ return func (path , * args , ** kwargs )
36
+
37
+ return wrapper
38
+
39
+
40
+ # Python 3.8 compatibility
41
+ wrapper = SkipRepeatAbsolutePaths ().wrap
16
42
17
43
18
44
@functools .singledispatch
45
+ @wrapper
19
46
def mkpath (name : pathlib .Path , mode = 0o777 , verbose = True , dry_run = False ):
20
47
"""Create a directory and any missing ancestor directories.
21
48
@@ -26,12 +53,6 @@ def mkpath(name: pathlib.Path, mode=0o777, verbose=True, dry_run=False):
26
53
If 'verbose' is true, log the directory created.
27
54
Return the list of directories actually created.
28
55
"""
29
-
30
- global _path_created
31
-
32
- if str (name .absolute ()) in _path_created :
33
- return
34
-
35
56
if verbose and not name .is_dir ():
36
57
log .info ("creating %s" , name )
37
58
@@ -40,7 +61,6 @@ def mkpath(name: pathlib.Path, mode=0o777, verbose=True, dry_run=False):
40
61
41
62
try :
42
63
dry_run or name .mkdir (mode = mode , parents = True , exist_ok = True )
43
- _path_created .add (name .absolute ())
44
64
except OSError as exc :
45
65
raise DistutilsFileError (f"could not create '{ name } ': { exc .args [- 1 ]} " )
46
66
@@ -185,8 +205,6 @@ def remove_tree(directory, verbose=True, dry_run=False):
185
205
Any errors are ignored (apart from being reported to stdout if 'verbose'
186
206
is true).
187
207
"""
188
- global _path_created
189
-
190
208
if verbose >= 1 :
191
209
log .info ("removing '%s' (and everything under it)" , directory )
192
210
if dry_run :
@@ -196,10 +214,8 @@ def remove_tree(directory, verbose=True, dry_run=False):
196
214
for cmd in cmdtuples :
197
215
try :
198
216
cmd [0 ](cmd [1 ])
199
- # remove dir from cache if it's already there
200
- abspath = os .path .abspath (cmd [1 ])
201
- if abspath in _path_created :
202
- _path_created .remove (abspath )
217
+ # Clear the cache
218
+ SkipRepeatAbsolutePaths .clear ()
203
219
except OSError as exc :
204
220
log .warning ("error removing %s: %s" , directory , exc )
205
221
0 commit comments