Skip to content

Auto Hash

auto_hash

Auto-hash decorator for generating __hash__ on class instances.

Provides the auto_hash decorator that generates __hash__
based on class fields. Works on plain classes with __slots__ or
__annotations__.

Can be used as @auto_hash, @auto_hash(), or
@auto_hash(fields=[...]) to hash only specific attributes.

Does NOT generate __eq__ — combine with auto_eq when structural
equality is needed alongside hashing.

Useful for: Hashable data types and any type that requires
consistent hashing for sets or dictionary keys.

Example
@auto_hash
class Point2D:
    __slots__ = ("x", "y")

    def __init__(self, x: float, y: float) -> None:
        self.x = x
        self.y = y


p1 = Point2D(1.0, 2.0)
p2 = Point2D(1.0, 2.0)
assert hash(p1) == hash(p2)

With selective fields:

@auto_hash(fields=["id"])
class Record:
    __slots__ = ("id", "data")

    def __init__(self, id: str, data: str) -> None:
        self.id = id
        self.data = data


r1 = Record("abc", "payload-a")
r2 = Record("abc", "payload-b")
assert hash(r1) == hash(r2)

auto_hash(class_: type[T] | None = None, *, fields: Sequence[str] | None = None) -> type[T] | Callable[[type[T]], type[T]]

auto_hash(class_: type[T]) -> type[T]
auto_hash(
    class_: type[T], *, fields: Sequence[str] | None = None
) -> type[T]
auto_hash(
    class_: None = None,
    *,
    fields: Sequence[str] | None = None,
) -> Callable[[type[T]], type[T]]

Generate __hash__ for a class based on its fields.

Can be used as @auto_hash, @auto_hash(), or
@auto_hash(fields=[...]). Generates __hash__ only — does NOT
generate __eq__. Use auto_eq for structural equality
comparisons.

Parameters:

Name Type Description Default
class_ type[T] | None

The target class (when used directly as @auto_hash).
None when used with parentheses (@auto_hash() or
@auto_hash(fields=...)).

None
fields Sequence[str] | None

Optional sequence of field names to include in the hash.
When None, all fields declared in __slots__ or
__annotations__ are used.

None

Returns:

Type Description
type[T] | Callable[[type[T]], type[T]]

The decorated class if class_ is provided; otherwise a callable

type[T] | Callable[[type[T]], type[T]]

that can be used as a decorator.

Raises:

Type Description
TypeError

If no field names can be determined automatically and
fields is None.

Source code in src/forging_blocks/foundation/autohash/auto_hash.py
def auto_hash[T](
    class_: type[T] | None = None,
    *,
    fields: Sequence[str] | None = None,
) -> type[T] | Callable[[type[T]], type[T]]:
    """Generate ``__hash__`` for a class based on its fields.

    Can be used as ``@auto_hash``, ``@auto_hash()``, or
    ``@auto_hash(fields=[...])``. Generates ``__hash__`` only — does NOT
    generate ``__eq__``. Use `auto_eq` for structural equality
    comparisons.

    Args:
        class_: The target class (when used directly as ``@auto_hash``).
            ``None`` when used with parentheses (``@auto_hash()`` or
            ``@auto_hash(fields=...)``).
        fields: Optional sequence of field names to include in the hash.
            When ``None``, all fields declared in ``__slots__`` or
            ``__annotations__`` are used.

    Returns:
        The decorated class if *class_* is provided; otherwise a callable
        that can be used as a decorator.

    Raises:
        TypeError: If no field names can be determined automatically and
            *fields* is ``None``.

    """
    decorator = _AutoHashDecorator(fields=fields)

    if class_ is not None:
        return decorator(class_)
    return decorator