Skip to content

Commit

Permalink
Merge branch 'main' into FileSpec-variance
Browse files Browse the repository at this point in the history
  • Loading branch information
jaraco authored Aug 29, 2024
2 parents eb71932 + ba562cc commit 5cf91d5
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 19 deletions.
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ repos:
rev: v0.5.6
hooks:
- id: ruff
args: [--fix, --unsafe-fixes]
- id: ruff-format
37 changes: 19 additions & 18 deletions jaraco/path.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
Tools for working with files and file systems
"""

from __future__ import annotations

import os
import re
import itertools
Expand All @@ -16,8 +18,10 @@
import ctypes
import importlib
import pathlib
from typing import Mapping, Protocol, Union, runtime_checkable
from typing import TYPE_CHECKING, Mapping, Protocol, Union, runtime_checkable

if TYPE_CHECKING:
from typing_extensions import Self

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -289,24 +293,20 @@ class Symlink(str):

@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 symlink_to(self, target): ... # pragma: no cover
def __truediv__(self, other, /) -> Self: ...
def mkdir(self, *, exist_ok) -> object: ...
def write_text(self, content, /, *, encoding) -> object: ...
def write_bytes(self, content, /) -> object: ...
def symlink_to(self, target, /) -> object: ...


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


def build(
spec: FilesSpec,
prefix: Union[str, TreeMaker] = pathlib.Path(), # type: ignore[assignment]
prefix: str | TreeMaker = pathlib.Path(),
):
"""
Build a set of files/directories, as described by the spec.
Expand Down Expand Up @@ -338,23 +338,24 @@ def build(


@functools.singledispatch
def create(content: Union[str, bytes, FilesSpec], path):
def create(content: str | bytes | FilesSpec, path: TreeMaker) -> None:
path.mkdir(exist_ok=True)
build(content, prefix=path) # type: ignore[arg-type]
# Mypy only looks at the signature of the main singledispatch method. So it must contain the complete Union
build(content, prefix=path) # type: ignore[arg-type] # python/mypy#11727


@create.register
def _(content: bytes, path):
def _(content: bytes, path: TreeMaker) -> None:
path.write_bytes(content)


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


@create.register
def _(content: Symlink, path):
def _(content: Symlink, path: TreeMaker) -> None:
path.symlink_to(content)


Expand Down
5 changes: 4 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,8 @@ type = [
]



[tool.setuptools_scm]


[tool.pytest-enabler.mypy]
# Disabled due to jaraco/skeleton#143
10 changes: 10 additions & 0 deletions tests/test_path.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
import pathlib
import platform

import pytest
Expand Down Expand Up @@ -43,3 +44,12 @@ def test_is_hidden_Darwin():
target = os.path.expanduser('~/Library')
assert path.is_hidden(target)
assert path.is_hidden_Darwin(target)


def test_TreeMaker_Protocol() -> None:
# Ensure the validity of the TreeMaker Protocol both statically and at runtime
tree_maker: path.TreeMaker
tree_maker = pathlib.Path()
assert isinstance(tree_maker, path.TreeMaker)
tree_maker = path.Recording()
assert isinstance(tree_maker, path.TreeMaker)

0 comments on commit 5cf91d5

Please sign in to comment.