Skip to main content

mares

mark's result class for safe data retrieval

or, as i learnt from opus 4.5, a railway-oriented two-track result pattern for explicit success/failure handling

the class

@dataclass(frozen=True, slots=True)
class Result(Generic[T]):
    """
    `dataclasses.dataclass` representing a result for safe value retrieval

    attributes:
        `value: T`
            value to return or fallback value if erroneous
        `error: BaseException | None = None`
            exception if any

    methods:
        `def __bool__(self) -> bool: ...`
            method for boolean comparison for exception safety
        `def get(self) -> T: ...`
            method that raises or returns an error if the Result is erroneous
        `def map(self, func: Callable[[T], U]) -> Result[U]: ...`
            method that maps the value when not erroneous
        `def bind(self, func: Callable[[T], Result[U]]) -> Result[U]: ...`
            method that binds to another Result-returning function
        `def cry(self, string: bool = False) -> str: ...`
            method that returns the result value or raises an error
    """

    value: T
    error: BaseException | None = None

    def __bool__(self) -> bool:
        """
        method for boolean comparison for easier exception handling

        returns: `bool`
            that returns True if `self.error` is not None
        """
        return self.error is None

    def cry(self, string: bool = False) -> str:  # noqa: FBT001, FBT002
        """
        method that raises or returns an error if the Result is erroneous

        arguments:
            `string: bool = False`
                if `self.error` is an Exception, returns it as a string
                error message

        returns: `str`
            returns `self.error` as a string if `string` is True,
            or returns an empty string if `self.error` is None
        """

        if isinstance(self.error, BaseException):
            if string:
                message = f"{self.error}"
                name = self.error.__class__.__name__
                return f"{message} ({name})" if (message != "") else name

            raise self.error

        return ""

    def get(self) -> T:
        """
        method that returns the result value or raises an error

        returns: `T`
            returns `self.value` if `self.error` is None

        raises: `BaseException`
            if `self.error` is not None
        """
        if self.error is not None:
            raise self.error
        return self.value

    def map(self, func: Callable[[T], U]) -> "Result[U]":
        """
        method that maps the value when not erroneous

        arguments:
            `func: Callable[[T], U]`
                function to transform the value

        returns: `Result[U]`
            returns a new Result with the transformed value, or the same error
        """
        if self.error is not None:
            return Result(cast(U, self.value), error=self.error)
        return Result(func(self.value))

    def bind(self, func: Callable[[T], "Result[U]"]) -> "Result[U]":
        """
        method that binds to another Result-returning function

        arguments:
            `func: Callable[[T], Result[U]]`
                function to transform the value into a Result

        returns: `Result[U]`
            returns the bound Result, or the same error
        """
        if self.error is not None:
            return Result(cast(U, self.value), error=self.error)
        return func(self.value)

    @staticmethod
    def wrap(default: R) -> Callable[[Callable[P, R]], Callable[P, "Result[R]"]]:
        """decorator that wraps a non-Result-returning function to return a Result"""

        def result_decorator(func: Callable[P, R]) -> Callable[P, Result[R]]:
            @wraps(func)
            def wrapper(*args: P.args, **kwargs: P.kwargs) -> Result[R]:
                try:
                    return Result(func(*args, **kwargs))
                except Exception as exc:
                    return Result(default, error=exc)

            return wrapper

        return result_decorator

an example

def fetch_json(url: str) -> Result[dict[str, Any]]:
    try:
        with urllib.request.urlopen(url, timeout=10) as response:
            data = response.read().decode("utf-8")
        return Result(json.loads(data))
    except (OSError, ValueError, json.JSONDecodeError) as exc:
        return Result({}, error=exc)

def require_field(data: dict[str, Any], field: str) -> Result[dict[str, Any]]:
    if field not in data:
        return Result({}, error=KeyError(f"Missing field: {field}"))
    return Result(data)

return (
    fetch_json(f"https://jsonplaceholder.typicode.com/users/{randint(1, 10)}")
    .bind(lambda payload: require_field(payload, "name"))
    .map(lambda payload: str(payload["name"]))
)

bonus! this is available as a library, and as a quick insertion tool.

pip install mares

uv add mares

uvx mares inject path/to/file.py

Release files for mares 2026.5.15

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mares 2026.5.15
File Size Uploaded
mares-2026.5.15.tar.gz 6.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for mares 2026.5.15
File Interpreter ABI Platform
mares-2026.5.15-py3-none-any.whl Python 3 none any Details

Total release size: 15.5 kB

Release files / mares-2026.5.15.tar.gz

Download URL mares-2026.5.15.tar.gz
Size 6.2 kB
Tags Source
SHA-256 checksum
How to use checksums
dad136ea1b6976f8c41e043420bb2264274179ee64ffb7cf3fcd0c449f5972cf
BLAKE2b-256 checksum
How to use checksums
f48a843599dbdef236b73598ef3a7792d582ba7e5ee2051d60fe99b4e95635d3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.11 {"installer":{"name":"uv","version":"0.11.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / mares-2026.5.15-py3-none-any.whl

Download URL mares-2026.5.15-py3-none-any.whl
Size 9.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6e919ecd7e70480a4f21a2f964485a4152d50ef43ab68b1b14f8327bbb034dd6
BLAKE2b-256 checksum
How to use checksums
03ccf5cf3009ed46353146b196577b748f4a0ee1091ede8b3d91bd4f091e55e5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.11 {"installer":{"name":"uv","version":"0.11.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

2026.5.15 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page