Skip to content

Commit

Permalink
Fix TreeMaker Protocol, removing all type:ignore
Browse files Browse the repository at this point in the history
  • Loading branch information
Avasam committed Aug 26, 2024
1 parent f068602 commit a4f8fc6
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 19 deletions.
38 changes: 19 additions & 19 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,9 +18,10 @@
import ctypes
import importlib
import pathlib
from typing import Dict, Protocol, Union
from typing import runtime_checkable
from typing import TYPE_CHECKING, Dict, Protocol, Union, runtime_checkable

if TYPE_CHECKING:
from typing_extensions import Self

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -290,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 @@ -339,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
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 a4f8fc6

Please sign in to comment.