1- # from jaraco.path 3.7.1
1+ # from jaraco.path 3.7.2
2+
3+ from __future__ import annotations
24
35import functools
46import pathlib
5- from typing import Dict , Protocol , Union , runtime_checkable
7+ from typing import TYPE_CHECKING , Mapping , Protocol , Union , runtime_checkable
8+
9+ if TYPE_CHECKING :
10+ from typing_extensions import Self
611
712
813class Symlink (str ):
@@ -11,29 +16,25 @@ class Symlink(str):
1116 """
1217
1318
14- FilesSpec = Dict [str , Union [str , bytes , Symlink , 'FilesSpec' ]]
19+ FilesSpec = Mapping [str , Union [str , bytes , Symlink , 'FilesSpec' ]]
1520
1621
1722@runtime_checkable
1823class TreeMaker (Protocol ):
19- def __truediv__ (self , * args , ** kwargs ): ... # pragma: no cover
20-
21- def mkdir (self , ** kwargs ): ... # pragma: no cover
22-
23- def write_text (self , content , ** kwargs ): ... # pragma: no cover
24-
25- def write_bytes (self , content ): ... # pragma: no cover
26-
27- def symlink_to (self , target ): ... # pragma: no cover
24+ def __truediv__ (self , other , / ) -> Self : ...
25+ def mkdir (self , * , exist_ok ) -> object : ...
26+ def write_text (self , content , / , * , encoding ) -> object : ...
27+ def write_bytes (self , content , / ) -> object : ...
28+ def symlink_to (self , target , / ) -> object : ...
2829
2930
30- def _ensure_tree_maker (obj : Union [ str , TreeMaker ] ) -> TreeMaker :
31- return obj if isinstance (obj , TreeMaker ) else pathlib .Path (obj ) # type: ignore[return-value]
31+ def _ensure_tree_maker (obj : str | TreeMaker ) -> TreeMaker :
32+ return obj if isinstance (obj , TreeMaker ) else pathlib .Path (obj )
3233
3334
3435def build (
3536 spec : FilesSpec ,
36- prefix : Union [ str , TreeMaker ] = pathlib .Path (), # type: ignore[assignment]
37+ prefix : str | TreeMaker = pathlib .Path (),
3738):
3839 """
3940 Build a set of files/directories, as described by the spec.
@@ -65,23 +66,24 @@ def build(
6566
6667
6768@functools .singledispatch
68- def create (content : Union [ str , bytes , FilesSpec ] , path ) :
69+ def create (content : str | bytes | FilesSpec , path : TreeMaker ) -> None :
6970 path .mkdir (exist_ok = True )
70- build (content , prefix = path ) # type: ignore[arg-type]
71+ # Mypy only looks at the signature of the main singledispatch method. So it must contain the complete Union
72+ build (content , prefix = path ) # type: ignore[arg-type] # python/mypy#11727
7173
7274
7375@create .register
74- def _ (content : bytes , path ) :
76+ def _ (content : bytes , path : TreeMaker ) -> None :
7577 path .write_bytes (content )
7678
7779
7880@create .register
79- def _ (content : str , path ) :
81+ def _ (content : str , path : TreeMaker ) -> None :
8082 path .write_text (content , encoding = 'utf-8' )
8183
8284
8385@create .register
84- def _ (content : Symlink , path ) :
86+ def _ (content : Symlink , path : TreeMaker ) -> None :
8587 path .symlink_to (content )
8688
8789
0 commit comments