2
2
import functools
3
3
4
4
from typing import Dict , Union
5
+ from typing import runtime_checkable
6
+ from typing import Protocol
5
7
6
8
7
9
####
8
- # from jaraco.path 3.4 .1
10
+ # from jaraco.path 3.7 .1
9
11
10
- FilesSpec = Dict [str , Union [str , bytes , 'FilesSpec' ]] # type: ignore
11
12
13
+ class Symlink (str ):
14
+ """
15
+ A string indicating the target of a symlink.
16
+ """
17
+
18
+
19
+ FilesSpec = Dict [str , Union [str , bytes , Symlink , 'FilesSpec' ]]
20
+
21
+
22
+ @runtime_checkable
23
+ class TreeMaker (Protocol ):
24
+ def __truediv__ (self , * args , ** kwargs ): ... # pragma: no cover
25
+
26
+ def mkdir (self , ** kwargs ): ... # pragma: no cover
27
+
28
+ def write_text (self , content , ** kwargs ): ... # pragma: no cover
29
+
30
+ def write_bytes (self , content ): ... # pragma: no cover
12
31
13
- def build (spec : FilesSpec , prefix = pathlib .Path ()):
32
+ def symlink_to (self , target ): ... # pragma: no cover
33
+
34
+
35
+ def _ensure_tree_maker (obj : Union [str , TreeMaker ]) -> TreeMaker :
36
+ return obj if isinstance (obj , TreeMaker ) else pathlib .Path (obj ) # type: ignore[return-value]
37
+
38
+
39
+ def build (
40
+ spec : FilesSpec ,
41
+ prefix : Union [str , TreeMaker ] = pathlib .Path (), # type: ignore[assignment]
42
+ ):
14
43
"""
15
44
Build a set of files/directories, as described by the spec.
16
45
@@ -25,21 +54,25 @@ def build(spec: FilesSpec, prefix=pathlib.Path()):
25
54
... "__init__.py": "",
26
55
... },
27
56
... "baz.py": "# Some code",
28
- ... }
57
+ ... "bar.py": Symlink("baz.py"),
58
+ ... },
59
+ ... "bing": Symlink("foo"),
29
60
... }
30
61
>>> target = getfixture('tmp_path')
31
62
>>> build(spec, target)
32
63
>>> target.joinpath('foo/baz.py').read_text(encoding='utf-8')
33
64
'# Some code'
65
+ >>> target.joinpath('bing/bar.py').read_text(encoding='utf-8')
66
+ '# Some code'
34
67
"""
35
68
for name , contents in spec .items ():
36
- create (contents , pathlib . Path (prefix ) / name )
69
+ create (contents , _ensure_tree_maker (prefix ) / name )
37
70
38
71
39
72
@functools .singledispatch
40
73
def create (content : Union [str , bytes , FilesSpec ], path ):
41
74
path .mkdir (exist_ok = True )
42
- build (content , prefix = path ) # type: ignore
75
+ build (content , prefix = path ) # type: ignore[arg-type]
43
76
44
77
45
78
@create .register
@@ -52,5 +85,10 @@ def _(content: str, path):
52
85
path .write_text (content , encoding = 'utf-8' )
53
86
54
87
88
+ @create .register
89
+ def _ (content : Symlink , path ):
90
+ path .symlink_to (content )
91
+
92
+
55
93
# end from jaraco.path
56
94
####
0 commit comments