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.2.tar.gz (6.5 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.2-py3-none-any.whl (7.0 kB view details)

Uploaded Python 3

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

Hashes for persistentobjects-0.2.2.tar.gz
Algorithm Hash digest
SHA256 8964c9c73178f3e2b780e1eded6be64685331962f64e5bebc087672c51dc3629
MD5 8044230b0703dd2941fbb5bf6559b154
BLAKE2b-256 1d1636e173684ce52c7f531d0c23f6f35ad770e413ab120db6fbe40023bb60bb

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for persistentobjects-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 c08cb3b71ff5746489e11d3e7de8fa1ae5866a5b25d31cd231f9e3351fcd13a1
MD5 de6b4cf5ab501f9911b8a22c3f929d2b
BLAKE2b-256 958d524d82284ccfce4a95e5452df7cb2b5289bc3950f8c48c29bdf16dfbb476

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