Skip to content

Commit 2cb9b45

Browse files
committed
Vendor jaraco.path.build from jaraco.path 3.5
1 parent 64ae8f6 commit 2cb9b45

File tree

1 file changed

+104
-0
lines changed

1 file changed

+104
-0
lines changed

Diff for: tests/_path.py

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# from jaraco.path 3.5
2+
3+
import functools
4+
import pathlib
5+
from typing import Dict, Union
6+
7+
try:
8+
from typing import Protocol, runtime_checkable
9+
except ImportError: # pragma: no cover
10+
# Python 3.7
11+
from typing_extensions import Protocol, runtime_checkable # type: ignore
12+
13+
14+
FilesSpec = Dict[str, Union[str, bytes, 'FilesSpec']] # type: ignore
15+
16+
17+
@runtime_checkable
18+
class TreeMaker(Protocol):
19+
def __truediv__(self, *args, **kwargs):
20+
... # pragma: no cover
21+
22+
def mkdir(self, **kwargs):
23+
... # pragma: no cover
24+
25+
def write_text(self, content, **kwargs):
26+
... # pragma: no cover
27+
28+
def write_bytes(self, content):
29+
... # pragma: no cover
30+
31+
32+
def _ensure_tree_maker(obj: Union[str, TreeMaker]) -> TreeMaker:
33+
return obj if isinstance(obj, TreeMaker) else pathlib.Path(obj) # type: ignore
34+
35+
36+
def build(
37+
spec: FilesSpec,
38+
prefix: Union[str, TreeMaker] = pathlib.Path(), # type: ignore
39+
):
40+
"""
41+
Build a set of files/directories, as described by the spec.
42+
43+
Each key represents a pathname, and the value represents
44+
the content. Content may be a nested directory.
45+
46+
>>> spec = {
47+
... 'README.txt': "A README file",
48+
... "foo": {
49+
... "__init__.py": "",
50+
... "bar": {
51+
... "__init__.py": "",
52+
... },
53+
... "baz.py": "# Some code",
54+
... }
55+
... }
56+
>>> target = getfixture('tmp_path')
57+
>>> build(spec, target)
58+
>>> target.joinpath('foo/baz.py').read_text(encoding='utf-8')
59+
'# Some code'
60+
"""
61+
for name, contents in spec.items():
62+
create(contents, _ensure_tree_maker(prefix) / name)
63+
64+
65+
@functools.singledispatch
66+
def create(content: Union[str, bytes, FilesSpec], path):
67+
path.mkdir(exist_ok=True)
68+
build(content, prefix=path) # type: ignore
69+
70+
71+
@create.register
72+
def _(content: bytes, path):
73+
path.write_bytes(content)
74+
75+
76+
@create.register
77+
def _(content: str, path):
78+
path.write_text(content, encoding='utf-8')
79+
80+
81+
class Recording:
82+
"""
83+
A TreeMaker object that records everything that would be written.
84+
85+
>>> r = Recording()
86+
>>> build({'foo': {'foo1.txt': 'yes'}, 'bar.txt': 'abc'}, r)
87+
>>> r.record
88+
['foo/foo1.txt', 'bar.txt']
89+
"""
90+
91+
def __init__(self, loc=pathlib.PurePosixPath(), record=None):
92+
self.loc = loc
93+
self.record = record if record is not None else []
94+
95+
def __truediv__(self, other):
96+
return Recording(self.loc / other, self.record)
97+
98+
def write_text(self, content, **kwargs):
99+
self.record.append(str(self.loc))
100+
101+
write_bytes = write_text
102+
103+
def mkdir(self, **kwargs):
104+
return

0 commit comments

Comments
 (0)