1- # from jaraco.path 3.7
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
6- from typing import runtime_checkable
7+ from collections .abc import Mapping
8+ from typing import TYPE_CHECKING , Protocol , Union , runtime_checkable
9+
10+ if TYPE_CHECKING :
11+ from typing_extensions import Self
712
813
914class Symlink (str ):
@@ -12,29 +17,25 @@ class Symlink(str):
1217 """
1318
1419
15- FilesSpec = Dict [str , Union [str , bytes , Symlink , 'FilesSpec' ]] # type: ignore
20+ FilesSpec = Mapping [str , Union [str , bytes , Symlink , 'FilesSpec' ]]
1621
1722
1823@runtime_checkable
1924class TreeMaker (Protocol ):
20- def __truediv__ (self , * args , ** kwargs ): ... # pragma: no cover
21-
22- def mkdir (self , ** kwargs ): ... # pragma: no cover
23-
24- def write_text (self , content , ** kwargs ): ... # pragma: no cover
25-
26- def write_bytes (self , content ): ... # pragma: no cover
27-
28- def symlink_to (self , target ): ... # pragma: no cover
25+ def __truediv__ (self , other , / ) -> Self : ...
26+ def mkdir (self , * , exist_ok ) -> object : ...
27+ def write_text (self , content , / , * , encoding ) -> object : ...
28+ def write_bytes (self , content , / ) -> object : ...
29+ def symlink_to (self , target , / ) -> object : ...
2930
3031
31- def _ensure_tree_maker (obj : Union [ str , TreeMaker ] ) -> TreeMaker :
32- return obj if isinstance (obj , TreeMaker ) else pathlib .Path (obj ) # type: ignore
32+ def _ensure_tree_maker (obj : str | TreeMaker ) -> TreeMaker :
33+ return obj if isinstance (obj , TreeMaker ) else pathlib .Path (obj )
3334
3435
3536def build (
3637 spec : FilesSpec ,
37- prefix : Union [ str , TreeMaker ] = pathlib .Path (), # type: ignore
38+ prefix : str | TreeMaker = pathlib .Path (),
3839):
3940 """
4041 Build a set of files/directories, as described by the spec.
@@ -66,23 +67,24 @@ def build(
6667
6768
6869@functools .singledispatch
69- def create (content : Union [ str , bytes , FilesSpec ] , path ) :
70+ def create (content : str | bytes | FilesSpec , path : TreeMaker ) -> None :
7071 path .mkdir (exist_ok = True )
71- build (content , prefix = path ) # type: ignore
72+ # Mypy only looks at the signature of the main singledispatch method. So it must contain the complete Union
73+ build (content , prefix = path ) # type: ignore[arg-type] # python/mypy#11727
7274
7375
7476@create .register
75- def _ (content : bytes , path ) :
77+ def _ (content : bytes , path : TreeMaker ) -> None :
7678 path .write_bytes (content )
7779
7880
7981@create .register
80- def _ (content : str , path ) :
82+ def _ (content : str , path : TreeMaker ) -> None :
8183 path .write_text (content , encoding = 'utf-8' )
8284
8385
8486@create .register
85- def _ (content : Symlink , path ) :
87+ def _ (content : Symlink , path : TreeMaker ) -> None :
8688 path .symlink_to (content )
8789
8890
0 commit comments