Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ maintainers = [
requires-python = ">=3.9"
dependencies = [
"fsspec >=2024.5.0",
"pathlib-abc ==0.4.3",
"pathlib-abc ==0.5.0",
]
classifiers = [
"Programming Language :: Python :: 3",
Expand Down
19 changes: 7 additions & 12 deletions upath/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,9 @@ def with_segments(self, *pathsegments: JoinablePathLike) -> Self:
)

def __str__(self) -> str:
return self.__vfspath__()

def __vfspath__(self) -> str:
return self._chain_parser.chain(self._chain.to_list())[0]

def __repr__(self) -> str:
Expand Down Expand Up @@ -484,12 +487,8 @@ def iterdir(self) -> Iterator[Self]:
_, _, name = name.removesuffix(sep).rpartition(self.parser.sep)
yield base.with_segments(str(base), name)

def __open_rb__(self, buffering: int = -1) -> BinaryIO:
block_size = _buffering2blocksize("wb", buffering)
kw = {}
if block_size is not None:
kw["block_size"] = block_size
return self.fs.open(self.path, mode="rb", **kw)
def __open_reader__(self) -> BinaryIO:
return self.fs.open(self.path, mode="rb")

def readlink(self) -> Self:
raise NotImplementedError
Expand Down Expand Up @@ -523,12 +522,8 @@ def mkdir(
if not self.is_dir():
raise FileExistsError(str(self))

def __open_wb__(self, buffering: int = -1) -> BinaryIO:
block_size = _buffering2blocksize("wb", buffering)
kw = {}
if block_size is not None:
kw["block_size"] = block_size
return self.fs.open(self.path, mode="wb", **kw)
def __open_writer__(self, mode: Literal["a", "w", "x"]) -> BinaryIO:
return self.fs.open(self.path, mode=f"{mode}b")

# --- upath overrides ---------------------------------------------

Expand Down
8 changes: 4 additions & 4 deletions upath/extensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,8 @@ def iterdir(self) -> Iterator[Self]:
for pth in self.__wrapped__.iterdir():
yield self._from_upath(pth)

def __open_rb__(self, buffering: int = -1) -> BinaryIO:
return self.__wrapped__.__open_rb__(buffering)
def __open_reader__(self) -> BinaryIO:
return self.__wrapped__.__open_reader__()

def readlink(self) -> Self:
return self._from_upath(self.__wrapped__.readlink())
Expand All @@ -144,8 +144,8 @@ def mkdir(
) -> None:
self.__wrapped__.mkdir(mode=mode, parents=parents, exist_ok=exist_ok)

def __open_wb__(self, buffering: int = -1) -> BinaryIO:
return self.__wrapped__.__open_wb__(buffering)
def __open_writer__(self, mode: Literal["a", "w", "x"]) -> BinaryIO:
return self.__wrapped__.__open_writer__(mode)

@overload
def open(
Expand Down
12 changes: 5 additions & 7 deletions upath/types/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,12 @@
from typing import overload
from typing import runtime_checkable

from pathlib_abc import magic_open

from upath.types._abc import JoinablePath
from upath.types._abc import PathInfo
from upath.types._abc import PathParser
from upath.types._abc import ReadablePath
from upath.types._abc import WritablePath
from upath.types._abc import vfsopen

if TYPE_CHECKING:
if sys.version_info > (3, 11):
Expand Down Expand Up @@ -110,7 +109,7 @@ def open(
errors: str | None = None,
newline: str | None = None,
) -> IO[Any]:
return magic_open(self, mode, buffering, encoding, errors, newline)
return vfsopen(self, mode, buffering, encoding, errors, newline)


if sys.version_info >= (3, 14):
Expand All @@ -125,11 +124,10 @@ class CompatJoinablePath(Protocol):
# not available in Python 3.9.* pathlib:
# - `parser`
# - `with_segments`
# - `__vfspath__`
# - `full_match`
__slots__ = ()

def __str__(self) -> str: ...

@property
def anchor(self) -> str: ...
@property
Expand Down Expand Up @@ -161,8 +159,8 @@ def parents(self) -> Sequence[Self]: ...
@runtime_checkable
class CompatReadablePath(CompatJoinablePath, Protocol):
# not available in Python 3.9.* pathlib:
# - `__open_rb__`
# - `info`
# - `__open_reader__`
# - `copy`
# - `copy_into`
# - `walk`
Expand All @@ -187,7 +185,7 @@ def readlink(self) -> Self: ...
@runtime_checkable
class CompatWritablePath(CompatJoinablePath, Protocol):
# not available in Python 3.9.* pathlib:
# - `__open_wb__`
# - `__open_writer__`
# - `_copy_from`
__slots__ = ()

Expand Down
4 changes: 4 additions & 0 deletions upath/types/_abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@
from pathlib_abc import PathParser
from pathlib_abc import ReadablePath
from pathlib_abc import WritablePath
from pathlib_abc import vfsopen
from pathlib_abc import vfspath

__all__ = [
"JoinablePath",
"ReadablePath",
"WritablePath",
"PathInfo",
"PathParser",
"vfsopen",
"vfspath",
]
31 changes: 28 additions & 3 deletions upath/types/_abc.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ from typing import Any
from typing import BinaryIO
from typing import Callable
from typing import Iterator
from typing import Literal
from typing import Protocol
from typing import Sequence
from typing import TextIO
from typing import TypeVar
from typing import runtime_checkable

Expand All @@ -26,7 +28,7 @@ class JoinablePath(ABC):
@abstractmethod
def with_segments(self, *pathsegments: str | Self) -> Self: ...
@abstractmethod
def __str__(self) -> str: ...
def __vfspath__(self) -> str: ...
@property
def anchor(self) -> str: ...
@property
Expand Down Expand Up @@ -61,7 +63,7 @@ class ReadablePath(JoinablePath):
@abstractmethod
def info(self) -> PathInfo: ...
@abstractmethod
def __open_rb__(self, buffering: int = ...) -> BinaryIO: ...
def __open_reader__(self) -> BinaryIO: ...
def read_bytes(self) -> bytes: ...
def read_text(
self,
Expand Down Expand Up @@ -93,7 +95,7 @@ class WritablePath(JoinablePath):
@abstractmethod
def mkdir(self) -> None: ...
@abstractmethod
def __open_wb__(self, buffering: int = ...) -> BinaryIO: ...
def __open_writer__(self, mode: Literal["a", "w", "x"]) -> BinaryIO: ...
def write_bytes(self, data: bytes) -> int: ...
def write_text(
self,
Expand All @@ -119,3 +121,26 @@ class PathInfo(Protocol):
def is_dir(self, *, follow_symlinks: bool = True) -> bool: ...
def is_file(self, *, follow_symlinks: bool = True) -> bool: ...
def is_symlink(self) -> bool: ...

class SupportsOpenReader(Protocol):
def __open_reader__(self) -> BinaryIO: ...

class SupportsOpenWriter(Protocol):
def __open_writer__(self, mode: Literal["a", "w", "x"]) -> BinaryIO: ...

class SupportsOpenUpdater(Protocol):
def __open_updater__(self, mode: Literal["r+", "w+", "+r", "+w"]) -> BinaryIO: ...

def vfsopen(
obj: SupportsOpenReader | SupportsOpenWriter | SupportsOpenUpdater,
mode="r",
buffering: int = -1,
encoding: str | None = None,
errors: str | None = None,
newline: str | None = None,
) -> BinaryIO | TextIO: ...

class SupportsVFSPath(Protocol):
def __vfspath__(self) -> str: ...

def vfspath(obj: SupportsVFSPath) -> str: ...
Loading