PersistentObjects 0.1.5__tar.gz → 0.1.7__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PersistentObjects
3
- Version: 0.1.5
3
+ Version: 0.1.7
4
4
  Summary: JSON-backed attribute-persistent object with namespace support
5
5
  Author: Tornado300
6
6
  License-Expression: MIT
@@ -34,5 +34,8 @@ pobject.second_value = "foo"
34
34
  namespace = pobject.namespace("test_namespace") # creates a new namespace (new subdict in json)
35
35
  namespace.third_value = [10, 5]
36
36
 
37
+
38
+ print(pobject.test_namespace.third_value) # alternate way to access namespaces
39
+
37
40
  pobject.temp_ = True # suffixed with '_' so it will not be saved and behaves like a normal attribute.
38
41
  ```
@@ -1,5 +1,6 @@
1
1
  import json, os, threading
2
2
 
3
+
3
4
  class _PersistentState:
4
5
  _instances = {}
5
6
 
@@ -22,6 +23,7 @@ class _PersistentState:
22
23
  self._path = os.path.abspath(path)
23
24
  self._lock = threading.Lock()
24
25
  self._data = {}
26
+ self._defaults = {}
25
27
  self._load()
26
28
 
27
29
  def _load(self):
@@ -40,16 +42,24 @@ class _PersistentState:
40
42
 
41
43
  def __getattr__(self, name):
42
44
  if name.startswith("_"):
43
- raise AttributeError(name)
45
+ raise AttributeError(f"Cannot access private attribute '{name}'")
44
46
  if name.endswith("_"):
45
- try:
47
+ try:
46
48
  return super().__getattribute__(name[:-1])
47
49
  except AttributeError:
48
- raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{name}'.\n Notice: Attribute '{name}' is not persistent!")
50
+ raise AttributeError(
51
+ f"'{self.__class__.__name__}' object has no attribute '{name}'.\n Notice: Attribute '{name}' is not persistent!"
52
+ )
49
53
  try:
50
- return self._data[name]
54
+ value = self._data[name]
55
+ # If it's a dict, return it as a namespace
56
+ if isinstance(value, dict):
57
+ return _Namespace(self, name)
58
+ return value
51
59
  except KeyError:
52
- raise AttributeError(name)
60
+ raise AttributeError(
61
+ f"'{type(self).__name__}' object has no attribute '{name}'"
62
+ )
53
63
 
54
64
  def __setattr__(self, name, value):
55
65
  if name.startswith("_"):
@@ -87,15 +97,18 @@ class _Namespace:
87
97
  self._initialized = True
88
98
  self._root = root
89
99
  self._key = key
100
+ self._defaults = {}
90
101
 
91
102
  def __getattr__(self, name):
92
103
  if name.startswith("_"):
93
104
  raise AttributeError(name)
94
105
  if name.endswith("_"):
95
- try:
106
+ try:
96
107
  return super().__getattribute__(name[:-1])
97
108
  except AttributeError:
98
- raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{name}'.\n Notice: Attribute '{name}' is not persistent!")
109
+ raise AttributeError(
110
+ f"'{self.__class__.__name__}' object has no attribute '{name}'.\n Notice: Attribute '{name}' is not persistent!"
111
+ )
99
112
  try:
100
113
  return self._root._data[self._key][name]
101
114
  except KeyError:
@@ -115,12 +128,64 @@ class _Namespace:
115
128
  bucket[name] = value
116
129
  self._root._save()
117
130
 
131
+ def setdefault(self, name: str, value):
132
+ """Set a value only if the key doesn't already exist. Registers the value as the default for reset()."""
133
+ self._defaults[name] = value
134
+ with self._root._lock:
135
+ bucket = self._root._data.setdefault(self._key, {})
136
+ if name not in bucket:
137
+ bucket[name] = value
138
+ self._root._save()
139
+ return self._root._data[self._key][name]
140
+
141
+ def reset(self, name: str | None = None):
142
+ """Reset a key to its default value, or all keys if no name is given.
143
+
144
+ Raises KeyError if the key has no registered default.
145
+ """
146
+ with self._root._lock:
147
+ bucket = self._root._data.setdefault(self._key, {})
148
+ if name is not None:
149
+ if name not in self._defaults:
150
+ raise KeyError(
151
+ f"No default registered for '{name}'. Use setdefault() first."
152
+ )
153
+ bucket[name] = self._defaults[name]
154
+ else:
155
+ for key, value in self._defaults.items():
156
+ bucket[key] = value
157
+ self._root._save()
158
+
118
159
 
119
160
  class PersistentObject(_PersistentState):
120
161
  def namespace(self, name) -> _Namespace:
121
162
  return _Namespace(self, name)
122
163
 
164
+ def setdefault(self, name: str, value):
165
+ """Set a value only if the key doesn't already exist. Registers the value as the default for reset()."""
166
+ self._defaults[name] = value
167
+ with self._lock:
168
+ if name not in self._data:
169
+ self._data[name] = value
170
+ self._save()
171
+ return self._data[name]
172
+
173
+ def reset(self, name: str | None = None):
174
+ """Reset a key to its default value, or all keys if no name is given.
123
175
 
176
+ Raises KeyError if the key has no registered default.
177
+ """
178
+ with self._lock:
179
+ if name is not None:
180
+ if name not in self._defaults:
181
+ raise KeyError(
182
+ f"No default registered for '{name}'. Use setdefault() first."
183
+ )
184
+ self._data[name] = self._defaults[name]
185
+ else:
186
+ for key, value in self._defaults.items():
187
+ self._data[key] = value
188
+ self._save()
124
189
 
125
190
 
126
191
  __all__ = ["PersistentObject"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PersistentObjects
3
- Version: 0.1.5
3
+ Version: 0.1.7
4
4
  Summary: JSON-backed attribute-persistent object with namespace support
5
5
  Author: Tornado300
6
6
  License-Expression: MIT
@@ -34,5 +34,8 @@ pobject.second_value = "foo"
34
34
  namespace = pobject.namespace("test_namespace") # creates a new namespace (new subdict in json)
35
35
  namespace.third_value = [10, 5]
36
36
 
37
+
38
+ print(pobject.test_namespace.third_value) # alternate way to access namespaces
39
+
37
40
  pobject.temp_ = True # suffixed with '_' so it will not be saved and behaves like a normal attribute.
38
41
  ```
@@ -21,5 +21,8 @@ pobject.second_value = "foo"
21
21
  namespace = pobject.namespace("test_namespace") # creates a new namespace (new subdict in json)
22
22
  namespace.third_value = [10, 5]
23
23
 
24
+
25
+ print(pobject.test_namespace.third_value) # alternate way to access namespaces
26
+
24
27
  pobject.temp_ = True # suffixed with '_' so it will not be saved and behaves like a normal attribute.
25
28
  ```
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "PersistentObjects"
7
- version = "0.1.5"
7
+ version = "0.1.7"
8
8
  description = "JSON-backed attribute-persistent object with namespace support"
9
9
  authors = [
10
10
  { name="Tornado300" }