A simple immutable dictionary implementation with hashing support and performance optimizations
85
Automatic JSON serialization support and monkeypatch utilities for seamless integration with JSON libraries. Provides custom encoders and system-wide patches for transparent frozendict serialization.
Custom JSON encoder that handles frozendict serialization by converting to regular dictionaries.
class FrozendictJsonEncoder(JSONEncoder):
"""
JSON encoder that can serialize frozendict instances.
Automatically converts frozendict objects to regular dicts during
JSON serialization while preserving all other JSONEncoder functionality.
"""
def default(self, obj):
"""
Convert frozendict to dict for JSON serialization.
Parameters:
- obj: Object to serialize
Returns:
dict: Regular dict if obj is frozendict, otherwise delegates to parent
"""Usage Example:
import json
from frozendict import frozendict, FrozendictJsonEncoder
# Create frozendict with nested data
data = frozendict({
'name': 'Alice',
'settings': frozendict({'theme': 'dark', 'notifications': True}),
'tags': ['admin', 'developer']
})
# Serialize using custom encoder
json_string = json.dumps(data, cls=FrozendictJsonEncoder, indent=2)
print(json_string)
# {
# "name": "Alice",
# "settings": {
# "theme": "dark",
# "notifications": true
# },
# "tags": ["admin", "developer"]
# }
# Deserialize back to regular dicts
restored = json.loads(json_string)
# Note: restored will contain regular dicts, not frozendictsPatch the standard json module to automatically handle frozendict serialization.
def patchOrUnpatchJson(*, patch, warn=True):
"""
Patch or unpatch JSON module to handle frozendict serialization.
Parameters:
- patch: bool, True to apply patch, False to remove patch
- warn: bool, whether to show warnings about patching (default: True)
Returns:
None
Effects:
- When patched: json.dumps() automatically handles frozendict objects
- When unpatched: json.dumps() raises TypeError for frozendict objects
"""Usage Example:
import json
from frozendict import frozendict, patchOrUnpatchJson
# Enable automatic JSON support
patchOrUnpatchJson(patch=True, warn=False)
data = frozendict({'key': 'value', 'number': 42})
# Now json.dumps works directly with frozendict
json_string = json.dumps(data)
print(json_string) # {"key": "value", "number": 42}
# Disable automatic support
patchOrUnpatchJson(patch=False)
# Now json.dumps would raise TypeError
try:
json.dumps(data)
except TypeError as e:
print(f"Error: {e}") # Object of type frozendict is not JSON serializableSupport for the high-performance orjson library with automatic frozendict handling.
def patchOrUnpatchOrjson(*, patch, warn=True):
"""
Patch or unpatch orjson module to handle frozendict serialization.
Parameters:
- patch: bool, True to apply patch, False to remove patch
- warn: bool, whether to show warnings about patching (default: True)
Returns:
None
Effects:
- When patched: orjson.dumps() automatically handles frozendict objects
- When unpatched: orjson.dumps() raises TypeError for frozendict objects
"""Usage Example:
# Requires: pip install orjson
import orjson
from frozendict import frozendict, patchOrUnpatchOrjson
# Enable orjson support
patchOrUnpatchOrjson(patch=True)
data = frozendict({'performance': 'high', 'speed': 'fast'})
# orjson now handles frozendict automatically
json_bytes = orjson.dumps(data)
json_string = json_bytes.decode('utf-8')
print(json_string) # {"performance": "high", "speed": "fast"}
# Restore original behavior
patchOrUnpatchOrjson(patch=False)Patch collections.abc.MutableMapping to properly exclude frozendict from mutable mapping checks.
def patchOrUnpatchMutableMappingSubclasshook(*, patch, warn=True):
"""
Patch or unpatch MutableMapping to exclude frozendict.
Parameters:
- patch: bool, True to apply patch, False to remove patch
- warn: bool, whether to show warnings about patching (default: True)
Returns:
None
Effects:
- When patched: isinstance(frozendict(), MutableMapping) returns False
- When unpatched: isinstance(frozendict(), MutableMapping) might return True
"""Usage Example:
from collections.abc import MutableMapping, Mapping
from frozendict import frozendict, patchOrUnpatchMutableMappingSubclasshook
# Apply the patch
patchOrUnpatchMutableMappingSubclasshook(patch=True)
d = frozendict({'a': 1, 'b': 2})
# frozendict is correctly identified as non-mutable
print(isinstance(d, Mapping)) # True (it is a mapping)
print(isinstance(d, MutableMapping)) # False (it is not mutable)
# Remove the patch
patchOrUnpatchMutableMappingSubclasshook(patch=False)Apply or remove all monkeypatches at once for complete integration.
def patchOrUnpatchAll(*, patch, warn=True, raise_orjson=False):
"""
Apply or remove all monkeypatches at once.
Parameters:
- patch: bool, True to apply all patches, False to remove all patches
- warn: bool, whether to show warnings about patching (default: True)
- raise_orjson: bool, raise exception if orjson patch fails (default: False)
Returns:
None
Effects:
Applies/removes all of:
- JSON module patching
- OrJSON module patching (if available)
- MutableMapping subclass hook patching
"""Usage Example:
import json
from frozendict import frozendict, patchOrUnpatchAll
# Enable all integrations
patchOrUnpatchAll(patch=True, warn=False)
# Now everything works seamlessly
data = frozendict({'integrated': True, 'seamless': True})
json_result = json.dumps(data) # Works automatically
# Disable all integrations
patchOrUnpatchAll(patch=False, warn=False)class MonkeypatchWarning(Warning):
"""
Warning class for monkeypatch operations.
Issued when monkeypatch operations encounter potentially
problematic situations or when patches are applied/removed.
"""Usage Example:
import warnings
from frozendict import patchOrUnpatchAll, MonkeypatchWarning
# Monitor monkeypatch warnings
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always")
# This might issue warnings about patching
patchOrUnpatchAll(patch=True, warn=True)
for warning in w:
if issubclass(warning.category, MonkeypatchWarning):
print(f"Monkeypatch warning: {warning.message}")When importing frozendict, the following occurs automatically:
# Automatically executed on import:
patchOrUnpatchAll(patch=True, warn=False)This means that JSON serialization support is enabled by default when you import frozendict, providing seamless integration without explicit setup.
Extending FrozendictJsonEncoder for additional custom types:
import json
from frozendict import FrozendictJsonEncoder
from datetime import datetime
class ExtendedJsonEncoder(FrozendictJsonEncoder):
def default(self, obj):
if isinstance(obj, datetime):
return obj.isoformat()
return super().default(obj)
# Use extended encoder
data = frozendict({
'timestamp': datetime.now(),
'nested': frozendict({'key': 'value'})
})
json_string = json.dumps(data, cls=ExtendedJsonEncoder)Apply only specific patches for controlled integration:
from frozendict import (
patchOrUnpatchJson,
patchOrUnpatchMutableMappingSubclasshook
)
# Enable only JSON support, not orjson
patchOrUnpatchJson(patch=True, warn=False)
patchOrUnpatchMutableMappingSubclasshook(patch=True, warn=False)
# orjson patching is not applied, giving more controlTemporarily enable patches for specific operations:
import json
from contextlib import contextmanager
from frozendict import frozendict, patchOrUnpatchJson
@contextmanager
def json_patched():
patchOrUnpatchJson(patch=True, warn=False)
try:
yield
finally:
patchOrUnpatchJson(patch=False, warn=False)
# Use within context
data = frozendict({'temp': 'patch'})
with json_patched():
result = json.dumps(data) # Works with patch
# Outside context, patch is removedInstall with Tessl CLI
npx tessl i tessl/pypi-frozendictevals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10