Skip to main content

Try to enforce various types of function purity in Python

Project description

Latest Version Python Versions Build Status Documentation Status

pure-function-decorators

Decorators to try to enforce various types of function purity in Python

Mostly vibe-coded, though I hope to whittle down any issues

Super-quick Start

Requires: Python 3.10 to 3.13

Install through pip:

pip install pure-function-decorators
from pure_function_decorators import (
    enforce_deterministic,
    forbid_globals,
    forbid_side_effects,
    immutable_arguments,
)


@forbid_globals()
def bad(x):
    return x + CONST

CONST = 10
bad(1)   # Raises NameError

Documentation

The complete documentation can be found at the pure-function-decorators home page

Features

Existing decorators

  • immutable_arguments deep-copies inputs before invoking the wrapped callable so callers never observe in-place mutations. By default the decorator raises when a mutation is detected, and it can instead log warnings with warn_only=True.
  • enforce_deterministic reruns a function and compares its results so you can gate functions that rely on deterministic behavior.
  • forbid_globals prevents a function from reading or mutating module-level state by sandboxing its globals. Pass check_names=True to also fail decoration when bytecode references globals outside the allow-list, or set sandbox=False to keep only the bytecode-based validation.
  • forbid_side_effects instruments builtin operations that commonly mutate process state (e.g. file writes, subprocess launches) to surface accidental side effects.

Future purity checks to explore

The current decorators focus on globals, determinism, and structural immutability. Additional checks that build on the same inspection hooks could include:

  • Non-deterministic source guards — wrap time-, randomness-, and UUID-related modules (time, datetime, random, uuid, secrets) to ensure a supposedly pure function does not sample entropy or wall-clock timestamps.
  • Environment isolation — raise when a function touches environment variables, current working directory, or other process-wide configuration through os.environ, os.chdir, or similar APIs.
  • I/O safelists — expand the forbid_side_effects strategy with dedicated helpers that specifically deny file, socket, or HTTP operations unless a pure-safe allowlist is provided.
  • Mutable default detection — detect functions whose default arguments or closed-over state are mutable so callers do not accidentally share state across invocations.
  • Dependency purity enforcement — verify that functions only call other decorated or safelisted pure functions by walking the bytecode or AST.

These ideas could live alongside the existing decorators as optional opt-in guards so projects can combine them to match their definition of purity.

Frequently asked questions

Can these decorators be enabled globally, like perl's strict pragma?

No. Python does not provide a hook that automatically wraps every function that is imported or defined after a module loads. The decorators in this project operate by returning a new callable, so each target function (or method) has to be wrapped explicitly. You can build your own helpers that iterate over a module or class and decorate selected callables, but the library cannot apply itself universally without the caller opting in on a per-function basis.

What about leaning on the descriptor protocol to auto-wrap methods?

Descriptors only help when attribute access goes through a class that you control, and Python already turns functions defined on a class into descriptors that bind methods at lookup time. Swapping in a custom descriptor still requires you to opt in for each attribute you expose, and it cannot cover free functions or methods defined on classes outside your control. You could build a metaclass or __setattr__ hook that decorates attributes as they are assigned, but that still imposes an explicit opt-in boundary (the metaclass or base class) rather than letting a library blanket the entire interpreter.

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

pure_function_decorators-0.1.2.tar.gz (58.8 kB view details)

Uploaded Source

Built Distribution

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

pure_function_decorators-0.1.2-py3-none-any.whl (14.3 kB view details)

Uploaded Python 3

File details

Details for the file pure_function_decorators-0.1.2.tar.gz.

File metadata

File hashes

Hashes for pure_function_decorators-0.1.2.tar.gz
Algorithm Hash digest
SHA256 fb3701e3e29892ecfe9eff91d5bcbf2872822a11175e3bc868e6f25c04bc9016
MD5 3611217d9bc64c38791df693e25e6fcf
BLAKE2b-256 f2bf81fa18b9f2972951dfb36eb740ad00c73ec6711a5722f4750c534dadf8de

See more details on using hashes here.

File details

Details for the file pure_function_decorators-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for pure_function_decorators-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 077a775c5b04c63088814da56fe1f4ceffa76ae0ec1a9081d6275264ebeb089c
MD5 940ed96721105f01fbb8a5b8c6579ee8
BLAKE2b-256 0fc8fed89845bc85b5da495ae0de3b430a3a5bd5818df7f912a839c615d53d0f

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