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.1.tar.gz (6.1 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.1-py3-none-any.whl (6.7 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: persistentobjects-0.2.1.tar.gz
  • Upload date:
  • Size: 6.1 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.1.tar.gz
Algorithm Hash digest
SHA256 a95ace11a33e8d2927f1746d9d30765e6537e2432539f2a5562360cd6d78e6ff
MD5 63681a66d7ad5185554ef5a14992c068
BLAKE2b-256 1237b50e75377fd604814ff109b362afdacc07ddbc175a9dc9e341b7566a2483

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for persistentobjects-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 e662493bf9c8d6c6c2009b8a1166a71fb3f85351053dac83f854bbc63667c229
MD5 0cb14f97eff9029ce69c745431d73778
BLAKE2b-256 414f0e6a136f42f231d4ae8401ee88a6952b34ef695253214aec46ab13c2956a

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