From 1f0f53fde37787a04bf5861fcc028b73d219b71d Mon Sep 17 00:00:00 2001 From: Christoph Kuhnke Date: Thu, 8 Aug 2024 13:22:22 +0200 Subject: [PATCH] #156: Fixed implementation of BucketPath.parent (#157) * #156: Fixed implementation of BucketPath.parent * Prepare release 0.13.0 --- doc/changes/changelog.md | 2 ++ doc/changes/changes_0.13.0.md | 5 ++++ doc/design/bucketpath.rst | 52 +++++++++++++++++------------------ exasol/bucketfs/_path.py | 6 ++-- exasol/bucketfs/version.py | 2 +- pyproject.toml | 2 +- 6 files changed, 38 insertions(+), 31 deletions(-) create mode 100644 doc/changes/changes_0.13.0.md diff --git a/doc/changes/changelog.md b/doc/changes/changelog.md index 5366190c..7711d59c 100644 --- a/doc/changes/changelog.md +++ b/doc/changes/changelog.md @@ -1,6 +1,7 @@ # 📝 Changes * [unreleased](unreleased.md) +* [0.13.0](changes_0.13.0.md) * [0.12.0](changes_0.12.0.md) * [0.11.0](changes_0.11.0.md) * [0.10.0](changes_0.10.0.md) @@ -19,6 +20,7 @@ hidden: --- unreleased +changes_0.13.0 changes_0.12.0 changes_0.11.0 changes_0.10.0 diff --git a/doc/changes/changes_0.13.0.md b/doc/changes/changes_0.13.0.md new file mode 100644 index 00000000..5333093f --- /dev/null +++ b/doc/changes/changes_0.13.0.md @@ -0,0 +1,5 @@ +# 0.13.0 - 2024-08-07 + +## Bugfixes + +* #156: Fixed implementation of BucketPath.parent \ No newline at end of file diff --git a/doc/design/bucketpath.rst b/doc/design/bucketpath.rst index 8ee229b1..e9cfde48 100644 --- a/doc/design/bucketpath.rst +++ b/doc/design/bucketpath.rst @@ -8,8 +8,8 @@ Problem Description Users of the BucketFS file system need to use it in various diffrent contexts like, from the outside of the DB interacting with bucketfs, from within the DB when accessing BucketFS paths from within UDFs. Also common actions/tasks like listing a directory are pretty tedious when just interacting with -the BucketFS API due to the fact that it does not know the concept of directories. So in -order to simplify and streamline frequently used path operations and also provide a uniform +the BucketFS API due to the fact that it does not know the concept of directories. So in +order to simplify and streamline frequently used path operations and also provide a uniform interface accross the actual system (local path, http, ...) behind the BucketFS path we need to have an abstraction for the user. @@ -38,7 +38,7 @@ Challenges with Current BucketFS Interactions Proposed Solution ================= -To address the identified issues with BucketFS interactions, we propose adding an abstraction layer that simplifies and standardizes these interactions across different contexts and operations. This approach is based on the design of the `pathlib` module in the Python standard library, which abstracts filesystem access across operating systems. +To address the identified issues with BucketFS interactions, we propose adding an abstraction layer that simplifies and standardizes these interactions across different contexts and operations. This approach is based on the design of the `pathlib` module in the Python standard library, which abstracts filesystem access across operating systems. Our proposed path abstraction layer will: @@ -152,50 +152,50 @@ Pathlike class Pathlike(Protocol): @property - def name: + def name(self) -> str: """ A string representing the final path component, excluding the drive and root, if any. """ @property - def suffix: + def suffix(self) -> str: """ The file extension of the final component, if any. """ @property - def root: + def root(self) -> str: """ A string representing the root, if any. """ @property - def parent: + def parent(self) -> PathLike: """ The logical parent of this path. """ - def as_uri(): + def as_uri(self) -> str: """ Represent the path as a file URI. Can be used to reconstruct the location/path. """ - def exists(): + def exists(self) -> bool: """ Return True if the path points to an existing file or directory. """ - def is_dir(): + def is_dir(self) -> bool: """ Return True if the path points to a directory, False if it points to another kind of file. """ - def is_file(): + def is_file(self) -> bool: """ Return True if the path points to a regular file, False if it points to another kind of file. """ - def read(chunk_size: int = 8192) -> Iterable[ByteString]: + def read(self, chunk_size: int = 8192) -> Iterable[ByteString]: """ Read the content of a the file behind this path. @@ -212,9 +212,9 @@ Pathlike FileNotFoundError: If the file does not exist. """ - def write(data: ByteString | BinaryIO | Iterable[ByteString]): + def write(self, data: ByteString | BinaryIO | Iterable[ByteString]): """ - Writes data to a this path. + Writes data to a this path. After successfully writing to this path `exists` will yield true for this path. If the file already existed it will be overwritten. @@ -226,7 +226,7 @@ Pathlike NotAFileError: if the pathlike object is not a file path. """ - def rm(): + def rm(self): """ Remove this file. @@ -238,7 +238,7 @@ Pathlike FileNotFoundError: If the file does not exist. """ - def rmdir(recursive: bool = False): + def rmdir(self, recursive: bool = False): """ Removes this directory. @@ -254,7 +254,7 @@ Pathlike PermissionError: If recursive is false and the directory is not empty. """ - def joinpath(*pathsegements) -> Pathlike: + def joinpath(self, *pathsegements) -> Pathlike: """ Calling this method is equivalent to combining the path with each of the given pathsegments in turn. @@ -262,7 +262,7 @@ Pathlike A new pathlike object pointing the combined path. """ - def walk() -> Tuple[Pathlike, List[str], List[str]]: + def walk(self) -> Tuple[Pathlike, List[str], List[str]]: """ Generate the file names in a directory tree by walking the tree either top-down or bottom-up. @@ -274,7 +274,7 @@ Pathlike A 3-tuple of (dirpath, dirnames, filenames). """ - def iterdir() -> Generator[Pathlike, None, None]: + def iterdir(self) -> Generator[Pathlike, None, None]: """ When the path points to a directory, yield path objects of the directory contents. @@ -286,7 +286,7 @@ Pathlike """ # Overload / for joining, see also joinpath or `pathlib.Path`. - def __truediv__(): + def __truediv__(self, other): """ """ @@ -310,7 +310,7 @@ Each backend must implement the ``as_uri`` method in a way that the location is """ Provides access to a bucket path served via http or https. """ - + # uri protocol specifies associated with this class protocol = ['bfs', 'bfss'] @@ -322,7 +322,7 @@ Each backend must implement the ``as_uri`` method in a way that the location is bucket: used for accssing and interacting with to the underlying bucket. path: of the file within the bucket. """ - + # Pathlike functionalities # ... @@ -365,7 +365,7 @@ Each modifier: """ Modifies a pathlike object so it will be locked into a specified root. """ - + def __init__(self, path: Pathlike, chroot='/'): """ Create a new Chroot. @@ -400,7 +400,7 @@ Each modifier: Returns: A path like object whith write proection. """ - + # Pathlike functionalities # Note: Non readonly actions should throw an exception # ... @@ -445,7 +445,7 @@ Factory & Builders A Pathlike object for the given uri. """ # type: LocalPath, BucketPath, Chroot ... - # + # # Note: based on the uri the factory should assemble the apropriate Pathlike object. # E.g.: type = _determine_type(path) @@ -494,4 +494,4 @@ Utilities Returns: A LocalPath (UdfPath) object. """ - + diff --git a/exasol/bucketfs/_path.py b/exasol/bucketfs/_path.py index 12e5cfee..a42de2cf 100644 --- a/exasol/bucketfs/_path.py +++ b/exasol/bucketfs/_path.py @@ -42,7 +42,7 @@ def root(self) -> str: """ @property - def parent(self) -> str: + def parent(self) -> PathLike: """ The logical parent of this path. """ @@ -289,8 +289,8 @@ def root(self) -> str: return self._path.root @property - def parent(self) -> str: - return self._path.parent.name + def parent(self) -> PathLike: + return BucketPath(self._path.parent, self._bucket_api) def as_uri(self) -> str: return self._path.as_uri() diff --git a/exasol/bucketfs/version.py b/exasol/bucketfs/version.py index 14e287e5..9ac5e232 100644 --- a/exasol/bucketfs/version.py +++ b/exasol/bucketfs/version.py @@ -5,6 +5,6 @@ # Do not edit this file manually! # If you need to change the version, do so in the project.toml, e.g. by using `poetry version X.Y.Z`. MAJOR = 0 -MINOR = 12 +MINOR = 13 PATCH = 0 VERSION = f"{MAJOR}.{MINOR}.{PATCH}" diff --git a/pyproject.toml b/pyproject.toml index f5e90768..92018aa3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,7 @@ packages = [ {include = "exasol"}, {include = "exasol_bucketfs_utils_python"} ] -version = "0.12.0" +version = "0.13.0" description = "BucketFS utilities for the Python programming language" license = "MIT"