-
-
Notifications
You must be signed in to change notification settings - Fork 84
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #446 from python/feature/jaraco-path-build
Use jaraco.path for generating the record and files
- Loading branch information
Showing
3 changed files
with
141 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
# from jaraco.path 3.5 | ||
|
||
import functools | ||
import pathlib | ||
from typing import Dict, Union | ||
|
||
try: | ||
from typing import Protocol, runtime_checkable | ||
except ImportError: # pragma: no cover | ||
# Python 3.7 | ||
from typing_extensions import Protocol, runtime_checkable # type: ignore | ||
|
||
|
||
FilesSpec = Dict[str, Union[str, bytes, 'FilesSpec']] # type: ignore | ||
|
||
|
||
@runtime_checkable | ||
class TreeMaker(Protocol): | ||
def __truediv__(self, *args, **kwargs): | ||
... # pragma: no cover | ||
|
||
def mkdir(self, **kwargs): | ||
... # pragma: no cover | ||
|
||
def write_text(self, content, **kwargs): | ||
... # pragma: no cover | ||
|
||
def write_bytes(self, content): | ||
... # pragma: no cover | ||
|
||
|
||
def _ensure_tree_maker(obj: Union[str, TreeMaker]) -> TreeMaker: | ||
return obj if isinstance(obj, TreeMaker) else pathlib.Path(obj) # type: ignore | ||
|
||
|
||
def build( | ||
spec: FilesSpec, | ||
prefix: Union[str, TreeMaker] = pathlib.Path(), # type: ignore | ||
): | ||
""" | ||
Build a set of files/directories, as described by the spec. | ||
Each key represents a pathname, and the value represents | ||
the content. Content may be a nested directory. | ||
>>> spec = { | ||
... 'README.txt': "A README file", | ||
... "foo": { | ||
... "__init__.py": "", | ||
... "bar": { | ||
... "__init__.py": "", | ||
... }, | ||
... "baz.py": "# Some code", | ||
... } | ||
... } | ||
>>> target = getfixture('tmp_path') | ||
>>> build(spec, target) | ||
>>> target.joinpath('foo/baz.py').read_text(encoding='utf-8') | ||
'# Some code' | ||
""" | ||
for name, contents in spec.items(): | ||
create(contents, _ensure_tree_maker(prefix) / name) | ||
|
||
|
||
@functools.singledispatch | ||
def create(content: Union[str, bytes, FilesSpec], path): | ||
path.mkdir(exist_ok=True) | ||
build(content, prefix=path) # type: ignore | ||
|
||
|
||
@create.register | ||
def _(content: bytes, path): | ||
path.write_bytes(content) | ||
|
||
|
||
@create.register | ||
def _(content: str, path): | ||
path.write_text(content, encoding='utf-8') | ||
|
||
|
||
class Recording: | ||
""" | ||
A TreeMaker object that records everything that would be written. | ||
>>> r = Recording() | ||
>>> build({'foo': {'foo1.txt': 'yes'}, 'bar.txt': 'abc'}, r) | ||
>>> r.record | ||
['foo/foo1.txt', 'bar.txt'] | ||
""" | ||
|
||
def __init__(self, loc=pathlib.PurePosixPath(), record=None): | ||
self.loc = loc | ||
self.record = record if record is not None else [] | ||
|
||
def __truediv__(self, other): | ||
return Recording(self.loc / other, self.record) | ||
|
||
def write_text(self, content, **kwargs): | ||
self.record.append(str(self.loc)) | ||
|
||
write_bytes = write_text | ||
|
||
def mkdir(self, **kwargs): | ||
return |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters