22import  functools 
33
44from  typing  import  Dict , Union 
5+ from  typing  import  runtime_checkable 
6+ from  typing  import  Protocol 
57
68
79#### 
8- # from jaraco.path 3.4 .1 
10+ # from jaraco.path 3.7 .1 
911
10- FilesSpec  =  Dict [str , Union [str , bytes , 'FilesSpec' ]]  # type: ignore 
1112
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 
1231
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+ ):
1443    """ 
1544    Build a set of files/directories, as described by the spec. 
1645
@@ -25,21 +54,25 @@ def build(spec: FilesSpec, prefix=pathlib.Path()):
2554    ...             "__init__.py": "", 
2655    ...         }, 
2756    ...         "baz.py": "# Some code", 
28-     ...     } 
57+     ...         "bar.py": Symlink("baz.py"), 
58+     ...     }, 
59+     ...     "bing": Symlink("foo"), 
2960    ... } 
3061    >>> target = getfixture('tmp_path') 
3162    >>> build(spec, target) 
3263    >>> target.joinpath('foo/baz.py').read_text(encoding='utf-8') 
3364    '# Some code' 
65+     >>> target.joinpath('bing/bar.py').read_text(encoding='utf-8') 
66+     '# Some code' 
3467    """ 
3568    for  name , contents  in  spec .items ():
36-         create (contents , pathlib . Path (prefix ) /  name )
69+         create (contents , _ensure_tree_maker (prefix ) /  name )
3770
3871
3972@functools .singledispatch  
4073def  create (content : Union [str , bytes , FilesSpec ], path ):
4174    path .mkdir (exist_ok = True )
42-     build (content , prefix = path )  # type: ignore 
75+     build (content , prefix = path )  # type: ignore[arg-type]  
4376
4477
4578@create .register  
@@ -52,5 +85,10 @@ def _(content: str, path):
5285    path .write_text (content , encoding = 'utf-8' )
5386
5487
88+ @create .register  
89+ def  _ (content : Symlink , path ):
90+     path .symlink_to (content )
91+ 
92+ 
5593# end from jaraco.path 
5694#### 
0 commit comments