JSON-backed attribute-persistent object with namespace support
Project description
PersistentObjects
A simple Python library that provides the PersistentObject class, which automatically saves all its attributes to a JSON file. Attributes are saved as soon as they are set.
[!IMPORTANT] In-place mutations like
.append(),.insert(),.extend(), etc. will not automatically save! Create a temp variable, mutate it, then reassign it back:temp = pobject.my_list temp.append("new item") pobject.my_list = temp # triggers save
Installation
pip install PersistentObjects
Usage
from PersistentObjects import PersistentObject
pobject = PersistentObject("save.json")
# attributes are saved to the json file immediately
pobject.first_value = 10
pobject.second_value = "foo"
# namespaces create sub-dicts in the json file
pobject.namespace("test_namespace")
pobject.test_namespace.third_value = [10, 5]
# or save the namespace to a variable
namespace = pobject.namespace("other_namespace")
namespace.value = 42
# suffix with '_' to make an attribute non-persistent (normal python attribute)
pobject.temp_ = True
# delete a persistent attribute
del pobject.first_value
Namespaces
Use namespace() to create a named section within the JSON file. After calling namespace(), you can access it via dot notation. Namespaces can be nested arbitrarily deep.
# create and access via dot notation
pobject.namespace("ui")
pobject.ui.theme = "dark"
pobject.ui.font_size = 14
# nested namespaces
pobject.namespace("ui").namespace("colors")
pobject.ui.colors.primary = "#ff0000"
pobject.ui.colors.accent = "#0000ff"
# or chain it
colors = pobject.namespace("ui").namespace("colors")
colors.primary = "#ff0000"
[!NOTE] You must call
.namespace()at least once before using dot-access. This is by design — without it, accessing a nonexistent attribute likepobject.typowould silently create an empty namespace instead of raising anAttributeError.
Supported types
Beyond the standard JSON types (str, int, float, bool, list, dict, None), the following Python types are automatically encoded and decoded:
| Type | JSON representation |
|---|---|
tuple |
{"__type__": "tuple", "__value__": [...]} |
set |
{"__type__": "set", "__value__": [...]} |
frozenset |
{"__type__": "frozenset", "__value__": [...]} |
bytes |
{"__type__": "bytes", "__value__": "<base64>"} |
datetime |
{"__type__": "datetime", "__value__": "<isoformat>"} |
date |
{"__type__": "date", "__value__": "<isoformat>"} |
time |
{"__type__": "time", "__value__": "<isoformat>"} |
Nested structures work too (e.g. a list of tuples, a set of tuples).
from datetime import datetime
pobject.my_set = {1, 2, 3}
pobject.my_tuple = ("a", "b", "c")
pobject.my_bytes = b"hello"
pobject.my_datetime = datetime(2025, 6, 15, 12, 30)
Type enforcement
Use settype() to register a type constraint on an attribute. Assigning a value of the wrong type raises a TypeError.
from typing import Any
pobject.settype("count", int)
pobject.count = 5 # ok
pobject.count = "five" # TypeError
# union types (Python 3.10+)
pobject.settype("value", int | None)
pobject.value = None # ok
# tuple of types
pobject.settype("multi", (int, str))
# Any removes the constraint
pobject.settype("count", Any)
# also works on namespaces
namespace.settype("volume", int | float)
Defaults
Use setdefault() to set a value only if the attribute doesn't already exist. It also registers the value for reset(). An optional type parameter combines setting a default with type enforcement.
pobject.setdefault("name", "default_name")
pobject.setdefault("count", 0, type=int) # sets default and enforces type
pobject.count = 99
pobject.reset("count") # back to 0
pobject.reset() # resets all attributes that have a registered default
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 persistentobjects-0.2.2.tar.gz.
File metadata
- Download URL: persistentobjects-0.2.2.tar.gz
- Upload date:
- Size: 6.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8964c9c73178f3e2b780e1eded6be64685331962f64e5bebc087672c51dc3629
|
|
| MD5 |
8044230b0703dd2941fbb5bf6559b154
|
|
| BLAKE2b-256 |
1d1636e173684ce52c7f531d0c23f6f35ad770e413ab120db6fbe40023bb60bb
|
File details
Details for the file persistentobjects-0.2.2-py3-none-any.whl.
File metadata
- Download URL: persistentobjects-0.2.2-py3-none-any.whl
- Upload date:
- Size: 7.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c08cb3b71ff5746489e11d3e7de8fa1ae5866a5b25d31cd231f9e3351fcd13a1
|
|
| MD5 |
de6b4cf5ab501f9911b8a22c3f929d2b
|
|
| BLAKE2b-256 |
958d524d82284ccfce4a95e5452df7cb2b5289bc3950f8c48c29bdf16dfbb476
|