A simple class that allows for error handling and eating inputs
Project description
NullPlus
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) → returnsself - Method calls (
obj.method(arg)) → returnsself - Mathematical operations (
obj + 10) → returnsself - Item access (
obj["key"]) → returnsself - Iteration (
for x in obj) → empty iterator - Context managers (
with obj:) → no-op - Boolean context (
if obj:) → alwaysFalse
Unset Sentinel Value
- Explicitly represents unset/undefined states
- Differentiates between explicit
Noneand missing values - Safe equality checks:
Unset() == Unset()→True - Distinct from all other values including
NoneandNull
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())→0int(Null())→-1float(Null())→nanlist(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?
-
Clear State Differentiation
Nullfor controlled error absorptionUnsetfor detecting unconfigured/missing values- Both distinct from
None
-
Eliminate Expensive Mistakes Avoid
AttributeError,TypeError, andNoneTypecrashes withNull -
Debugging-Friendly Preserve error context without disrupting control flow (
Null) Explicit state tracking (Unset) -
Context-Aware (Null) Works in sync/async contexts, math operations, and iterations
-
Semantic API Clearly signals intentional states in your codebase
-
Zero Dependencies Pure Python implementation
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nullplus-1.0.tar.gz.
File metadata
- Download URL: nullplus-1.0.tar.gz
- Upload date:
- Size: 5.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d66ba6017414247d37f1a5a36e72d5a087558596b788722469c28690ac271757
|
|
| MD5 |
e2650e1f8247676b1178c63a9fe0a232
|
|
| BLAKE2b-256 |
3e1e80c43cb45fdfeb51ec8d038db6eca7cb66da58284b3fe0e1e5d41cb104ad
|
File details
Details for the file nullplus-1.0-py3-none-any.whl.
File metadata
- Download URL: nullplus-1.0-py3-none-any.whl
- Upload date:
- Size: 5.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
303ac3e441f5d961841cca87c51f3ceb1558d7c1dac628742ef44464a1165ee7
|
|
| MD5 |
fb51a2f7afda31aadef5d2f30df28707
|
|
| BLAKE2b-256 |
f720d285e2941492c2afea4d10b0977c10e4a9e4b1a0c30917d74c126f182385
|