Skip to main content

A simple class that allows for error handling and eating inputs

Project description

NullPlus

PyPI version

A lightweight, robust implementation of the Null Object pattern that silently absorbs all operations while optionally carrying diagnostic data, plus an Unset class for differentiating between explicit None values and unset states.

# Instead of:
result = None
if result is None: 
    handle_error()

# Simply:
result = Null()
result.anything().you.want()  # No crashes, no fuss

# Differentiate unset vs explicit None:
config_value = Unset() if missing else value

Key Features

Universal Operation Absorption (Null)

  • Attribute access (obj.anything) → returns self
  • Method calls (obj.method(arg)) → returns self
  • Mathematical operations (obj + 10) → returns self
  • Item access (obj["key"]) → returns self
  • Iteration (for x in obj) → empty iterator
  • Context managers (with obj:) → no-op
  • Boolean context (if obj:) → always False

Unset Sentinel Value

  • Explicitly represents unset/undefined states
  • Differentiates between explicit None and missing values
  • Safe equality checks: Unset() == Unset()True
  • Distinct from all other values including None and Null

Easy Detection & Intentional Usage

if isinstance(result, Null):  # Explicit error check
    log_errors(result.data)   # Access stored diagnostics

if value is Unset():          # Detect unset state
    load_default_config()

Diagnostic Data Carrier (Null)

n = Null("Error: File not found", debug_id=42)
print(n)  # <Null: ("Error: File not found", {'debug_id': 42})>

Type-Safe Behavior (Null)

  • len(Null())0
  • int(Null())-1
  • float(Null())nan
  • list(Null())[]

Asynchronous Support (Null)

async with Null() as n:
    await n.some_operation()  # No errors

async for x in Null():
    print("Never runs")

Installation

pip install NullPlus

Usage Guide

Basic Error Handling (Null)

from NullPlus import Null

def safe_parser(data):
    try:
        return complex_operation(data)
    except Exception as e:
        return Null(e, original_data=data)

result = safe_parser(invalid_input)
print(result.anything)  # <Null: (ValueError('...'), {...})>

Unset Value Detection

from NullPlus import Unset

def process_config(config=Unset()):
    if config is Unset():
        print("Using default configuration")
        config = load_defaults()
    elif config is None:
        print("Explicitly disabled configuration")
    
    # Normal processing...

API Response Handling (Null)

def fetch_user_data():
    try:
        return api.get("/user")
    except ConnectionError as e:
        return Null(e, status_code=503)

data = fetch_user_data()
for item in data.get('items', Null()):
    # Safely handles either real data or Null
    process(item)

Mathematical Resilience (Null)

def calculate_metrics():
    return Null("Metrics unavailable") if error else real_metrics

result = calculate_metrics() * 10 / 5
print(result)  # <Null: 'Metrics unavailable'>

Advanced Diagnostics (Null)

error_state = Null(
    "Database connection failed",
    error_code=502,
    timestamp=datetime.now(),
    query_params=request.params
)

# Preserves complex diagnostic data
your_log_function(error_state.data)

Technical Highlights

Truthiness & Equality

# Null behavior
bool(Null())  # False
Null() == Null("different data")  # True
Null() == None  # False

# Unset behavior
Unset() == Unset()  # True
Unset() == None     # False
Unset() == Null()   # False
bool(Unset())       # True (normal object truthiness)

Operation Absorption Matrix (Null)

Operation Example Result
Attribute access Null().missing_attr <Null>
Method call Null()() <Null>
Item access Null()['key'] <Null>
Arithmetic Null() + 10 <Null>
Iteration list(Null()) []
Context manager with Null(): ... No-op
Async operations await Null() <Null>

Unset Key Properties

Property Description
Operation Safety Not operation-absorbing (normal attribute rules apply)
Primary Use Case Sentinel value for missing/undefined state
Distinct From None, Null(), empty containers, and falsey values
Serialization Represents as <Unset Value>

Why Choose NullPlus?

  1. Clear State Differentiation

    • Null for controlled error absorption
    • Unset for detecting unconfigured/missing values
    • Both distinct from None
  2. Eliminate Expensive Mistakes Avoid AttributeError, TypeError, and NoneType crashes with Null

  3. Debugging-Friendly Preserve error context without disrupting control flow (Null) Explicit state tracking (Unset)

  4. Context-Aware (Null) Works in sync/async contexts, math operations, and iterations

  5. Semantic API Clearly signals intentional states in your codebase

  6. Zero Dependencies Pure Python implementation

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

nullplus-1.1.1.tar.gz (5.8 kB view details)

Uploaded Source

Built Distribution

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

nullplus-1.1.1-py3-none-any.whl (5.5 kB view details)

Uploaded Python 3

File details

Details for the file nullplus-1.1.1.tar.gz.

File metadata

  • Download URL: nullplus-1.1.1.tar.gz
  • Upload date:
  • Size: 5.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.10

File hashes

Hashes for nullplus-1.1.1.tar.gz
Algorithm Hash digest
SHA256 f2e2fe164933da9b12452fcc99f47e8b79d4195a7474a63a097ccdacfb55cf97
MD5 e98f48bab09897eed26eba3ba216e2b4
BLAKE2b-256 16236ffa95501352576c71d60476e0e1f205a06d2e619e16659da4b0a19decdf

See more details on using hashes here.

File details

Details for the file nullplus-1.1.1-py3-none-any.whl.

File metadata

  • Download URL: nullplus-1.1.1-py3-none-any.whl
  • Upload date:
  • Size: 5.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.10

File hashes

Hashes for nullplus-1.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 3571ebde20fb45cd6421d19b566512868f3946f21ff76143090d6d2fb7183ddd
MD5 acb56b513564802326d1bcf21203ac72
BLAKE2b-256 c07fa72bcc454abd285b276feeb307f1da2739a265220aa030cdd30c36ecf175

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