Skip to main content

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 like pobject.typo would silently create an empty namespace instead of raising an AttributeError.

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

persistentobjects-0.2.3.tar.gz (6.4 kB view details)

Uploaded Source

Built Distribution

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

persistentobjects-0.2.3-py3-none-any.whl (6.9 kB view details)

Uploaded Python 3

File details

Details for the file persistentobjects-0.2.3.tar.gz.

File metadata

  • Download URL: persistentobjects-0.2.3.tar.gz
  • Upload date:
  • Size: 6.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for persistentobjects-0.2.3.tar.gz
Algorithm Hash digest
SHA256 102e53cca0b3524bcf671c837a2b326553f8774dc4c80002170efe9ef4291fcf
MD5 5bb5899504d759a1978f6732aa9c72a1
BLAKE2b-256 abc1ed24d7525534d9f5af5159c7c5223a2ceb126f41a19abd4724cd08f45f72

See more details on using hashes here.

File details

Details for the file persistentobjects-0.2.3-py3-none-any.whl.

File metadata

File hashes

Hashes for persistentobjects-0.2.3-py3-none-any.whl
Algorithm Hash digest
SHA256 7ba5a595d54d0cceaaa56475dcdb9ed57d9dbb91db9463c963c076af32c85ad2
MD5 1cf74b6358a003a09c09a15f4a276bb4
BLAKE2b-256 4e34b26d058677ddb31396aaa918fbda0eb74c27cedfc3368cf5e08f368ad2fd

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