from jaraco path 3 5 python 3 7 build a set of filesdirectories 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 tmppath buildspec target target joinpath foobaz py readtextencoding utf8 some code a treemaker object that records everything that would be written r recording build foo foo1 txt yes bar txt abc r r record foofoo1 txt bar txt from jaraco path 3 5 pragma no cover python 3 7 type ignore type ignore pragma no cover pragma no cover pragma no cover pragma no cover type ignore 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 type ignore 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
import functools
import pathlib
from typing import Dict, Union

try:
    from typing import Protocol, runtime_checkable
except ImportError:  
    
    from typing_extensions import Protocol, runtime_checkable  


FilesSpec = Dict[str, Union[str, bytes, 'FilesSpec']]  


@runtime_checkable
class TreeMaker(Protocol):
    def __truediv__(self, *args, **kwargs):
        ...  

    def mkdir(self, **kwargs):
        ...  

    def write_text(self, content, **kwargs):
        ...  

    def write_bytes(self, content):
        ...  


def _ensure_tree_maker(obj: Union[str, TreeMaker]) -> TreeMaker:
    return obj if isinstance(obj, TreeMaker) else pathlib.Path(obj)  


def build(
    spec: FilesSpec,
    prefix: Union[str, TreeMaker] = pathlib.Path(),  
):
    
    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)  


@create.register
def _(content: bytes, path):
    path.write_bytes(content)


@create.register
def _(content: str, path):
    path.write_text(content, encoding='utf-8')


@create.register
def _(content: str, path):
    path.write_text(content, encoding='utf-8')


class Recording:
    

    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