From 0e541007f2e169e6b52e7317a608cb4747c8bf5a Mon Sep 17 00:00:00 2001 From: Vince Reuter Date: Wed, 13 Mar 2024 12:43:43 +0100 Subject: [PATCH] use PathWrapperException more, fix typo, fix test; close #20 --- gertils/pathtools.py | 22 ++++++---------------- tests/test_pathtools.py | 15 ++++++--------- 2 files changed, 12 insertions(+), 25 deletions(-) diff --git a/gertils/pathtools.py b/gertils/pathtools.py index aa5e405..2f781ed 100644 --- a/gertils/pathtools.py +++ b/gertils/pathtools.py @@ -13,7 +13,7 @@ PW = TypeVar("PW", bound="PathWrapper") -@dataclass +@dataclass(frozen=True) class PathWrapper(ABC): """A Wrapper around a path that does some sort of validation""" @@ -28,18 +28,10 @@ def __post_init__(self) -> None: raise TypeError(f"Not a path, but {type(self.path).__name__}: {self.path}") self._invalidate() - def __setattr__(self, __name: str, __value: Any) -> None: # type: ignore[misc] - result = super().__setattr__(__name, __value) - self.__post_init__() - return result - @classmethod def from_string(cls: Type[PW], rawpath: str) -> PW: """Attempt to parse an instance from a raw string.""" - try: - return cls(Path(rawpath)) - except Exception as exc: - raise PathWrapperException(exc) from exc + return cls(Path(rawpath)) def to_string(self) -> str: """Return a string representation of this wrapped value.""" @@ -49,9 +41,7 @@ def to_string(self) -> str: class PathWrapperException(Exception): """Exception subtype for working with paths with a particular property""" - def __init__(self, original_exception: Exception) -> None: - super().__init__(str(original_exception)) - self.original = original_exception + pass class ExtantFile(PathWrapper): @@ -59,7 +49,7 @@ class ExtantFile(PathWrapper): def _invalidate(self) -> None: if not self.path.is_file(): - raise TypeError(f"Not an extant file: {self.path}") + raise PathWrapperException(f"Not an extant file: {self.path}") class ExtantFolder(PathWrapper): @@ -67,7 +57,7 @@ class ExtantFolder(PathWrapper): def _invalidate(self) -> None: if not self.path.is_dir(): - raise TypeError(f"Not an extant folder: {self.path}") + raise PathWrapperException(f"Not an extant folder: {self.path}") class NonExtantPath(PathWrapper): @@ -75,4 +65,4 @@ class NonExtantPath(PathWrapper): def _invalidate(self) -> None: if self.path.exists(): - raise TypeError(f"Path already exists: {self.path}") + raise PathWrapperException(f"Path already exists: {self.path}") diff --git a/tests/test_pathtools.py b/tests/test_pathtools.py index c1b823a..a07827b 100644 --- a/tests/test_pathtools.py +++ b/tests/test_pathtools.py @@ -2,7 +2,7 @@ """Tests for core utilities for working with paths""" -from dataclasses import dataclass +from dataclasses import dataclass, FrozenInstanceError from pathlib import Path from typing import * @@ -61,7 +61,7 @@ def test_path_wrapper_cannot_be_instantiated(wrapper): ) def test_path_wrapper_subtypes_invalidation(tmp_path, parameterisation): path = parameterisation.from_tmp_path(tmp_path) - with pytest.raises(TypeError) as error_context: + with pytest.raises(pathtools.PathWrapperException) as error_context: parameterisation.wrap_type(path) assert str(error_context.value) == f"{parameterisation.exp_err_msg_prefix}: {path}" @@ -76,12 +76,9 @@ def test_path_wrapper_immutability(tmp_path, parameterisation): good_path = tmp_path / "my-awesome-path" prepare_path(good_path) wrapper = parameterisation.wrap_type(good_path) - bad_path = parameterisation.from_tmp_path(tmp_path) - with pytest.raises(TypeError) as error_context: - wrapper.path = bad_path - assert ( - str(error_context.value) == f"{parameterisation.exp_err_msg_prefix}: {bad_path}" - ) + with pytest.raises(FrozenInstanceError) as error_context: + wrapper.path = wrapper.path + assert str(error_context.value) == f"cannot assign to field 'path'" @pytest.mark.parametrize(["wrap_type", "prepare_path"], PATH_PREPARATIONS.items()) @@ -96,7 +93,7 @@ def test_path_wrapper_subtypes_provide_path_attribute_access( @pytest.mark.parametrize(["wrap_type", "prepare_path"], PATH_PREPARATIONS.items()) -def test_path_wrapper_subtypes_rountrip_through_string( +def test_path_wrapper_subtypes_roundtrip_through_string( tmp_path, prepare_path, wrap_type ): path = tmp_path / "my-awesome-path"