Skip to main content

Taph creates objects that are guaranteed to be unchangeable, enabling predictable, pure functional programming patterns in Python.

Project description

Taph: Zero-Overhead Immutability for Python

PyPI - Version License Tests Coverage

Taph is a minimalist Python package for enforcing deep, zero-overhead immutability. Taph creates objects that are guaranteed to be unchangeable, enabling predictable, pure functional programming patterns in Python.

Taph's core value proposition: Fast & Reliable Immutability.


Key Features

  • Zero-Overhead: Achieves immutability using Python's Method Resolution Order (MRO) and metaclass injection.
  • Memory Efficiency: Enforces __slots__ usage, eliminating the memory footprint of __dict__ for every instance.
  • Deep Immutability: Recursively transforms nested mutable structures (like list, dict) into immutable counterparts (tuple, MappingProxyType) during class creation.
  • Zero Dependencies: A single-file core module built using the Python Standard Library.

Installation

pip install taph

Usage

Taph provides two modules:

  • Immutable for instantiable data objects
  • Namespace for static constants.

1. The Immutable Base Class

Use Immutable for creating value objects (data structures) whose state must never change after initialization.

Contract: Subclasses must define __slots__.

from taph import Immutable, ImmutableError

class Point(Immutable):
    __slots__ = ('x', 'y')

    def __init__(self, x: int, y: int):
        # IMPORTANT: Use super().__setattr__ for initialization!
        super().__setattr__('x', x)
        super().__setattr__('y', y)

p = Point(10, 20)

# Fails (ImmutableError)
try:
    p.x = 30
except ImmutableError as e:
    print(f"Success: {e}")

# Fails (ImmutableError)
try:
    del p.y
except ImmutableError as e:
    print(f"Success: {e}")

2. The Namespace Static Container

Use Namespace for static configuration, constants, or utility groups. Namespace classes are non-instantiable and their class attributes are ** frozen** at creation time.

from taph import Namespace, ImmutableError

class AppConfig(Namespace):
    __slots__ = () # Required, must be empty
    VERSION = "1.0.0"
    HOSTS = ["server-a", "server-b"] # Deeply frozen into a tuple

# Access attributes directly
print(f"Version: {AppConfig.VERSION}")
print(f"Hosts Type: {type(AppConfig.HOSTS)}") # <class 'tuple'>

# Fails (ImmutableError) - Cannot modify class attributes
try:
    AppConfig.TIMEOUT = 60
except ImmutableError as e:
    print(f"Success: {e}")

# Fails (ImmutableError) - Cannot instantiate
try:
    _ = AppConfig()
except ImmutableError as e:
    print(f"Success: {e}")

Deep Freezing

Taph's freeze utility ensures deep immutability by recursively converting mutable collections during class construction:

Mutable Type Taph Equivalent
list tuple
set frozenset
dict types.MappingProxyType

Custom objects must inherit from Immutable or Namespace, or freeze will raise an ImmutableError at class definition time.

Functional Style

Taph is the perfect foundation for functional programming in Python:

1. Pure Functions:

Pass Taph Immutable objects into functions with confidence that no side effects can occur.

from taph import Immutable

class User(Immutable):
    __slots__ = ('user_id', 'name', 'is_active')

    def __init__(self, user_id: int, name: str, is_active: bool = True):
        super().__setattr__('user_id', user_id)
        super().__setattr__('name', name)
        super().__setattr__('is_active', is_active)

# PURE FUNCTION: No side effects. Takes a User, returns a NEW User.
def deactivate_user(user: User) -> User:
    # This is the "copy-on-write" pattern.
    return User(
        user_id=user.user_id,
        name=user.name,
        is_active=False
    )

# --- Caller ---
user1 = User(101, 'Alice')
user2 = deactivate_user(user1)

# The original object is completely untouched. The system is predictable.
print(user1.is_active)  # -> True
print(user2.is_active)  # -> False
assert user1 is not user2

2. Stateless Systems:

Use Namespace to provide verifiably safe, global constants that cannot be accidentally mutated by any function.

from taph import Namespace

class Config(Namespace):
    __slots__ = ()
    TIMEOUT_SECONDS = 30
    SUPPORTED_METHODS = ('GET', 'POST')

def is_request_valid(request_duration: int, method: str) -> bool:
    # This function is predictable. Its behavior depends on its inputs and
    # constants that are guaranteed to be immutable.
    if method not in Config.SUPPORTED_METHODS:
        return False
    return request_duration < Config.TIMEOUT_SECONDS

# Config.TIMEOUT_SECONDS = 1 # Raises ImmutableError, protecting the function.

License

Taph is licensed under the Apache License 2.0. See the LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

taph-0.1.0.tar.gz (12.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

taph-0.1.0-py3-none-any.whl (14.3 kB view details)

Uploaded Python 3

File details

Details for the file taph-0.1.0.tar.gz.

File metadata

  • Download URL: taph-0.1.0.tar.gz
  • Upload date:
  • Size: 12.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for taph-0.1.0.tar.gz
Algorithm Hash digest
SHA256 3ca3f64e56f2c1017dbc6a6e5ba305cb0252f5249b96f6202a6113db37042d6a
MD5 23c7ae32baaa210d6246f5f393bb3e65
BLAKE2b-256 ad28992a440aeb17c996bec036413edd93820e721574fe809714d9b7b812d451

See more details on using hashes here.

File details

Details for the file taph-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: taph-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 14.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for taph-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 76d0b30fa1fd78baa1fc84e928b77aaaae289e5839174fbcbe2dc3cca70d0f4a
MD5 cd4ea253c1044cbdc9a04c68a6bb83b0
BLAKE2b-256 b6b2c2360ed4a6c3523d81ceb395d54dbd7699a23df02e06d4b189ed0a65da55

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page